编译前注意事项
- 编译基于tag为
RELEASE.2024-06-26T01-06-18Z
的版本- 处理安全扫描问题。如:敏感信息泄露、.js.map、跨域访问问题
- 需要准备两个工程,前端工程console和minio工程, 目录结构处理:
gowork/
│
└── src/
├── github.com
├── minio/
└── minio/
└── console/
- 若想直接使用处理后的源码,可以克隆minio仓库编辑即可
minio 直接拉取 minio工程进行编译即可,(其中依赖的console已经更换成
replace github.com/minio/console => gogs.zyjblogs.cn/minio/console v1.6.1-fix
git clone -b RELEASE.2024-06-26T01-06-18Z-fix https://gogs.zyjblogs.cn/minio/minio
- 若想直接使用修改后的minio二进制文件,详见蓝奏云链接: minio.tar.gz - 蓝奏云 (lanzout.com)
- 若想自行修改详见下文。
console编译
拉取minio的前端工程console
前端工程在console工程下web-app目录
#github.com上的仓库
git clone https://github.com/minio/console.git
#国内镜像加速仓库 gitcode
https://gitcode.com/gh_mirrors/console/console.git
修改package.json
在build下添加
GENERATE_SOURCEMAP=false
关闭sourcemap
json
"scripts": {
"start": "PORT=5005 react-scripts start",
"build": "GENERATE_SOURCEMAP=false react-scripts build",
"buildistanbulcoverage": "PORT=9090 USE_BABEL_PLUGIN_ISTANBUL=1 react-app-rewired build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"playwright": "PORT=5005 USE_BABEL_PLUGIN_ISTANBUL=1 react-app-rewired start",
"find-deadcode": "ts-prune -s consoleApi.ts | sh -c '(! grep -v \"used in module\")'"
},
编译
安装依赖
bash
#安装依赖
yarn install
#若出现证书问题可以忽略证书
## linux
export NODE_TLS_REJECT_UNAUTHORIZED=0 && yarn install
## windows
set NODE_TLS_REJECT_UNAUTHORIZED=0 && yarn install
编译前删除console工程下web-app/build目录
yarn build
修改获取不存在文件.js.map时返回文件且内容为index.html内容问题
console中有一个逻辑是访问不存在静态资源时会返回index.html的内容,因为安全漏洞扫描原因访问.js.map文件成功,虽然内容为index.html的内容,但是避免这类问题进行如下处理。
修改文件api/configure_console.go
- 导入os库
go
import (
"os"
// 其他库
)
- 添加环境变量
MINIO_HTTP_SERVER_INFO
修改通用的请求头Server显示的信息(默认为MinIO Console),进行自定义防止文件服务信息被泄露
修改方法
FileServerMiddleware
go
func FileServerMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
serverInfo := os.Getenv("MINIO_HTTP_SERVER_INFO")
if serverInfo == "" {
serverInfo = globalAppName
}
w.Header().Set("Server", serverInfo) // do not add version information
switch {
case strings.HasPrefix(r.URL.Path, "/ws"):
serveWS(w, r)
case strings.HasPrefix(r.URL.Path, "/api"):
next.ServeHTTP(w, r)
default:
buildFs, err := fs.Sub(portal_ui.GetStaticAssets(), "build")
if err != nil {
panic(err)
}
wrapHandlerSinglePageApplication(requestBounce(http.FileServer(http.FS(buildFs)))).ServeHTTP(w, r)
}
})
}
- 拦截.js.map
访问不存在资源且资源为资源为.js.map资源时返回404
修改方法
wrapHandlerSinglePageApplication
go
func wrapHandlerSinglePageApplication(h http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
handleSPA(w, r)
return
}
w.Header().Set("Content-Type", mimedb.TypeByExtension(filepath.Ext(r.URL.Path)))
nfw := ¬FoundRedirectRespWr{ResponseWriter: w}
h.ServeHTTP(nfw, r)
if nfw.status == http.StatusNotFound {
// 拦截 .js.map 文件
if strings.HasSuffix(r.URL.Path, ".js.map") {
http.NotFound(w, r)
return
}
handleSPA(w, r)
}
}
}
minio编译
拉取minio工程
#github.com上的仓库
git clone https://github.com/minio/minio.git
#国内镜像加速仓库 gitcode
https://gitcode.com/gh_mirrors/mi/minio.git
处理go.mod文件
添加替换文件中依赖
github.com/minio/console
为../console
bash
# 若为本地源代码执行下面命令进行处理
go mod edit --replace github.com/minio/console=../console
# 若想使用已经修改完成的console则使用
go mod edit --replace github.com/minio/console=gogs.zyjblogs.cn/minio/console@v1.6.1-fix
依赖下载
bash
go clean -modcache
go mod download
go mod tidy
修改项目源码
- 配置crossdomain.xml
原始minio访问
crossdomain.xml
可以看到返回xml内容:
xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy>
<allow-access-from domain="*" secure="false" />
</cross-domain-policy>
该配置安全扫描为不安全项,需要设置
allow-access-from
为具体的域名。现在把它修改为,读取配置的环境变量,然后设置为具体的域名,让其返回类似下面的xml,不能使用
*
号
xml
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.baidu.com" secure="false" />
<allow-access-from domain="zyjblogs.cn" secure="false" />
</cross-domain-policy>
修改步骤:
(1)修改项目中的internal/config/constants.go
文件,加入需要读取环境的名称,具体看修改后源码
const{}内添加两个环境变量,位置在 86~91行左右。 constants.go
const (
//.....
// 以下是自定的环境变量参数
// EnvMinIOAllowAccessFromDomain crossdomain.xml cross-domain-policy
EnvMinIOAllowAccessFromDomain = "MINIO_ALLOW_ACCESS_FROM_DOMAIN"
// EnvMinIOServerInfo api 通用的请求头Server显示的信息,进行自定义防止文件服务信息被泄露
EnvMinIOServerInfo = "MINIO_HTTP_SERVER_INFO"
)
(2)然后修改crossdomain.xml
对应的处理类cmd/crossdomain-xml-handler.go
,修改读取环境变量配置的值,具体查看修改后的文件[crossdomain-xml-handler.go](minio/minio @ RELEASE.2024-06-26T01-06-18Z-fix - 逝水无痕の代码仓库 (zyjblogs.cn)。
在变量
crossDomainXML
后添如下代码。代码位置32行位置
go
// 自定义crossdomain.xml
const crossDomainXMLPrefix = `<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy>`
const crossDomainXMLSuffix = `</cross-domain-policy>`
const allowAccessFromTemplate = `<allow-access-from domain="{{.Domain}}" secure="false" />`
替换方法
setCrossDomainPolicyMiddleware
为如下内容。 位置
go
func setCrossDomainPolicyMiddleware(h http.Handler) http.Handler {
// get env MINIO_ALLOW_ACCESS_FROM_DOMAIN
allowAccessFromDomain := os.Getenv(config.EnvMinIOAllowAccessFromDomain)
if allowAccessFromDomain == "" {
allowAccessFromDomain = "*"
}
// logger.Info("MINIO_ALLOW_ACCESS_FROM_DOMAIN=%s", allowAccessFromDomain)
// 如果配置了多个就需要解析一下
domains := strings.Split(allowAccessFromDomain, ",")
allowAccessFrom := crossDomainXMLPrefix
for _, domain := range domains {
// fill string template
buffer := &bytes.Buffer{}
tmpl, _ := template.New("tmp").Parse(allowAccessFromTemplate)
data := struct{ Domain string }{Domain: domain}
_ = tmpl.Execute(buffer, data)
allowAccessFrom += buffer.String()
}
allowAccessFrom += crossDomainXMLSuffix
// Write to ServeHTTP
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Look for 'crossdomain.xml' in the incoming request.
if r.URL.Path == crossDomainXMLEntity {
// Write the standard cross domain policy xml.
w.Write([]byte(allowAccessFrom))
// Request completed, no need to serve to other handlers.
return
}
h.ServeHTTP(w, r)
})
}
然后访问对应的地址,即可使用配置的xml。
http://IP:PORT/crossdomain.xml
(3) 添加功能:自定义响应头Server
的信息
请求minio接口时,返回的请求头会返回
Server: MinIO
,这样扫描会被针对扫描,需要修改为自定义的信息,例如这样:Server: MyOSS
,这样就可以不会暴露出文件服务器的信息了。
直接修改cmd/api-headers.go
文件中的setCommonHeaders
方法,读取配置环境变量,修改代码如下。可参考api-headers.go第55~59行
go
func setCommonHeaders(w http.ResponseWriter) {
// Set the "Server" http header.
// w.Header().Set(xhttp.ServerInfo, MinioStoreName)
// Set the "Server" http header.
serverInfo := os.Getenv(config.EnvMinIOServerInfo)
if serverInfo == "" {
serverInfo = MinioStoreName
}
w.Header().Set(xhttp.ServerInfo, serverInfo)
// Set `x-amz-bucket-region` only if region is set on the server
// by default minio uses an empty region.
if region := globalSite.Region(); region != "" {
w.Header().Set(xhttp.AmzBucketRegion, region)
}
w.Header().Set(xhttp.AcceptRanges, "bytes")
// Remove sensitive information
crypto.RemoveSensitiveHeaders(w.Header())
}
(4)添加功能:追加安全扫描提示的响应头
安全扫描提示需要响应头
ini
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: master-only
X-Xss-Protection: 1; mode=block
修改步骤:修改
cmd/generic-handlers.go
文件的addCustomHeadersMiddleware
方法,把缺少的响应头追加上即可,可参考修改后的源码generic-handlers.go第535~557行。
go
// 追加其他的请求头(安全漏洞提示处理)
header.Set("X-Permitted-Cross-Domain-Policies", "master-only")
header.Set("Referrer-Policy", "strict-origin-when-cross-origin")
header.Set("X-Frame-Options", "SAMEORIGIN")
编译项目
在minio工程下执行如下命令
参数介绍
go build -ldflags "-s -w" -o 编译后的二进制文件 项目工程目录
在minio工程执行构建命令时,使用
.
代表当前目录
bash
# window
go build -ldflags "-s -w" -o E:\minio.exe .
# linux
go build -ldflags "-s -w" -o ~/minio .
运行文件服务
使用环境变量配置启动参数:
sh
export MINIO_ROOT_USER=minioadmin
export MINIO_ROOT_PASSWORD=minioadmin
#export MINIO_BROWSER=false
export MINIO_API_CORS_ALLOW_ORIGIN="https://*.zyjblogs.cn,https://*example.com"
#新添加的参数
export MINIO_ALLOW_ACCESS_FROM_DOMAIN=*.zyjblogs.cn,*example.com
export MINIO_HTTP_SERVER_INFO=MyOSS
变量说明:
变量名称 | 说明 |
---|---|
MINIO_ROOT_USER | 管理控制台账号 |
MINIO_ROOT_PASSWORD | 管理控制台密码 |
MINIO_BROWSER | off关闭web控制台 |
MINIO_API_CORS_ALLOW_ORIGIN | api可使用域名 |
MINIO_ALLOW_ACCESS_FROM_DOMAIN | [new] crossdomain.xml文件的域名配置 |
MINIO_HTTP_SERVER_INFO | [new] 响应头Server的信息 |
使用9000端口启动文件服务:
sh
#!/bin/bash
export MINIO_ROOT_USER=minioadmin
export MINIO_ROOT_PASSWORD=minioadmin
#export MINIO_BROWSER=false
export MINIO_API_CORS_ALLOW_ORIGIN="https://*.zyjblogs.cn,https://*example.com"
export MINIO_ALLOW_ACCESS_FROM_DOMAIN=*.zyjblogs.cn,*example.com
export MINIO_HTTP_SERVER_INFO=MyOSS
nohup ./minio server data > minio.log 2>&1 &
参考: