Docker服務(wù)開放了這個端口,服務(wù)器分分鐘變?nèi)鈾C(jī)!

之前有很多朋友提過,當(dāng)使用docker-maven-plugin打包SpringBoot應(yīng)用的Docker鏡像時(shí),服務(wù)器需要開放2375端口。由于開放了端口沒有做任何安全保護(hù),會引起安全漏洞,被人入侵、挖礦、CPU飆升這些情況都有發(fā)生,今天我們來聊聊如何解決這個問題。

問題產(chǎn)生的原因

首先我們要明白問題產(chǎn)生的原因,才能更好地解決問題!

Docker為了實(shí)現(xiàn)集群管理,提供了遠(yuǎn)程管理的端口。Docker Daemon作為守護(hù)進(jìn)程運(yùn)行在后臺,可以執(zhí)行發(fā)送到管理端口上的Docker命令。

當(dāng)我們修改docker.service文件,修改啟動命令,加入-H tcp://0.0.0.0:2375時(shí),就會開放2375端口,且沒有任何加密和認(rèn)證過程,這種方式一般用在內(nèi)網(wǎng)測試環(huán)境。如果你的服務(wù)器部署在公網(wǎng)上,任何知道你IP的人,都可以管理這臺主機(jī)上的容器和鏡像,想想就覺得可怕。

解決思路

開放遠(yuǎn)程管理端口后,沒有做任何安全保護(hù)導(dǎo)致了這個問題。我們只要使用安全傳輸層協(xié)議(TLS)進(jìn)行傳輸并使用CA認(rèn)證即可。

制作證書及秘鑰

我們需要使用OpenSSL制作CA機(jī)構(gòu)證書、服務(wù)端證書和客戶端證書,以下操作均在安裝Docker的Linux服務(wù)器上進(jìn)行。

  • 首先創(chuàng)建一個目錄用于存儲生成的證書和秘鑰;
mkdir /mydata/docker-ca && cd /mydata/docker-ca
  • 創(chuàng)建CA證書私鑰,期間需要輸入兩次用戶名和密碼,生成文件為ca-key.pem;
openssl genrsa -aes256 -out ca-key.pem 4096
  • 根據(jù)私鑰創(chuàng)建CA證書,期間需要輸入上一步設(shè)置的私鑰密碼,生成文件為ca.pem;
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem
  • 創(chuàng)建服務(wù)端私鑰,生成文件為server-key.pem;
openssl genrsa -out server-key.pem 4096
  • 創(chuàng)建服務(wù)端證書簽名請求文件,用于CA證書給服務(wù)端證書簽名,生成文件server.csr;
openssl req -subj "/CN=*" -sha256 -new -key server-key.pem -out server.csr
  • 創(chuàng)建CA證書簽名好的服務(wù)端證書,期間需要輸入CA證書私鑰密碼,生成文件為server-cert.pem;
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
  • 創(chuàng)建客戶端私鑰,生成文件為key.pem;
openssl genrsa -out key.pem 4096
  • 創(chuàng)建客戶端證書簽名請求文件,用于CA證書給客戶證書簽名,生成文件client.csr;
openssl req -subj "/CN=client" -new -key key.pem -out client.csr
  • 為了讓秘鑰適合客戶端認(rèn)證,創(chuàng)建一個擴(kuò)展配置文件extfile-client.cnf;
echo extendedKeyUsage = clientAuth > extfile-client.cnf
  • 創(chuàng)建CA證書簽名好的客戶端證書,期間需要輸入CA證書私鑰密碼,生成文件為cert.pem;
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfi
  • 刪除創(chuàng)建過程中多余的文件;
rm -rf ca.srl server.csr client.csr extfile-client.cnf
  • 最終生成文件如下,有了它們我們就可以進(jìn)行基于TLS的安全訪問了。
ca.pem CA證書
ca-key.pem CA證書私鑰
server-cert.pem 服務(wù)端證書
server-key.pem 服務(wù)端證書私鑰
cert.pem 客戶端證書
key.pem 客戶端證書私鑰

配置Docker支持TLS

  • 用vim編輯器修改docker.service文件;
vi /usr/lib/systemd/system/docker.service
  • 修改以ExecStart開頭的配置,開啟TLS認(rèn)證,并配置好CA證書、服務(wù)端證書和服務(wù)端私鑰,修改內(nèi)容如下;
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --tlsverify --tlscacert=/mydata/docker-ca/ca.pem --tlscert=/m
  • 重啟Docker服務(wù),這樣我們的Docker服務(wù)就支持使用TLS進(jìn)行遠(yuǎn)程訪問了!
systemctl daemon-reload && systemctl restart docker

客戶端訪問

接下來我們將使用docker-maven-plugin來打包Docker鏡像,使用的代碼為原來的mall-tiny-docker例子。

  • 直接使用docker-maven-plugin打包試試,由于我們的插件版本有點(diǎn)低,使用新一點(diǎn)版本的Docker會出現(xiàn)如下問題,升級到1.2.2版本解決該問題;
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.1.0:build (build-image) on project mall-tiny-docker: Exception caught: com.spotify.docker.client.shaded.com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.spotify.docker.client.messages.RegistryAuth` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('desktop')
[ERROR] at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: java.util.LinkedHashMap["credsStore"])
[ERROR] -> [Help 1]
  • 修改完版本后打包,發(fā)現(xiàn)TLS不再支持http了,需要改用https,修改<dockerHost>配置為https;
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.2.2:build (build-image) on project mall-tiny-docker: Exception caught: Request error: GET http://192.168.3.101:2375/version: 400, body: Client sent an HTTP request to an HTTPS server. HTTP 400 Bad Request -> [Help 1]
  • 修改完成后再次打包,繼續(xù)失敗,需要添加對應(yīng)的客戶端證書才能訪問
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.2.2:build (build-image) on project mall-tiny-docker: Exception caught: java.util.concurrent.ExecutionException: com.spotify.docker.client.shaded.javax.ws.rs.ProcessingException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target -> [Help 1]
  • 將如下文件復(fù)制到指定目錄,這里復(fù)制到了I:\developer\env\docker-ca;
ca.pem CA證書
cert.pem 客戶端證書
key.pem 客戶端證書私鑰
  • 然后將該目錄配置在插件的<dockerCertPath>節(jié)點(diǎn)下,最終插件配置如下;
<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>1.2.2</version>
    <executions>
        <execution>
            <id>build-image</id>
            <phase>package</phase>
            <goals>
                <goal>build</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <imageName>mall-tiny/${project.artifactId}:${project.version}</imageName>
        <dockerHost>https://192.168.3.101:2375</dockerHost>
        <baseImage>java:8</baseImage>
        <entryPoint>["java", "-jar","/${project.build.finalName}.jar"]
        </entryPoint>
        <dockerCertPath>I:\developer\env\docker-ca</dockerCertPath>
        <resources>
            <resource>
                <targetPath>/</targetPath>
                <directory>${project.build.directory}</directory>
                <include>${project.build.finalName}.jar</include>
            </resource>
        </resources>
    </configuration>
</plugin>
  • 再次打包鏡像,發(fā)現(xiàn)已經(jīng)可以成功打包鏡像,從此我們的2375端口終于可以安全使用了!
[INFO] Building image mall-tiny/mall-tiny-docker:0.0.1-SNAPSHOT
Step 1/3 : FROM java:8

 ---> d23bdf5b1b1b
Step 2/3 : ADD /mall-tiny-docker-0.0.1-SNAPSHOT.jar //

 ---> 5cb5a64ccedd
Step 3/3 : ENTRYPOINT ["java", "-jar","/mall-tiny-docker-0.0.1-SNAPSHOT.jar"]

 ---> Running in 5f3ceefdd974
Removing intermediate container 5f3ceefdd974
 ---> ee9d0e2b0114
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built ee9d0e2b0114
Successfully tagged mall-tiny/mall-tiny-docker:0.0.1-SNAPSHOT
[INFO] Built mall-tiny/mall-tiny-docker:0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 20.550 s
[INFO] Finished at: 2020-07-31T15:02:15+08:00
[INFO] Final Memory: 50M/490M
[INFO] ------------------------------------------------------------------------

參考資料

官方文檔:https://docs.docker.com/engine/security/https/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容