使用mTLS保护Cockpit

2024-03-03, 杭州

Cockpit是企业级Linux(如CentOS、RHEL、Fedora和基于EL衍生出来的一众国产发行版等)开箱即用的网页端服务器管理面板,个人认为比某塔好用和安全得多,不知道为什么国内用的人不多。

如果你要用Cockpit官方的方式做mTLS,就得上FreeIPA之类的域控。但我只是想不被网络空间测绘工具测到这里有个登录面板然后被爆破。搁以往我会套一层Nginx,上auth_basic。但对Cockpit来说行不通,因为它已经使用了Authorization头来做用户登录认证。,而且这一点被官方标记为unfixable。有没有办法呢?有,在Nginx配置mTLS,如果不通,就会直接扔个400 Bad Request,攻击者从而无从嗅探背后究竟是个什么服务。

先自己签一套证书:

#!/usr/bin/env bash
openssl genpkey -algorithm RSA -out ca.key
openssl req -new -x509 -key ca.key -out ca.crt
openssl genpkey -algorithm RSA -out server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
openssl genpkey -algorithm RSA -out client.key
openssl req -new -key client.key -out client.csr
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt -certfile ca.crt

然后装载到nginx:

    server {
        listen         50505 ssl;
        server_name    _;
        ssl_certificate "/etc/pki/nginx/server.crt";
        ssl_certificate_key "/etc/pki/nginx/private/server.key";
        ssl_client_certificate "/etc/pki/nginx/ca.crt";
        ssl_verify_client on;
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers PROFILE=SYSTEM;
        ssl_prefer_server_ciphers on;


        location / {
            # Required to proxy the connection to Cockpit
            proxy_pass http://127.0.0.1:9090;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_ssl_verify off;
            # Required for web sockets to function
            proxy_http_version 1.1;
            proxy_buffering off;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";

            # Pass ETag header from Cockpit to clients.
            # See: https://github.com/cockpit-project/cockpit/issues/5239
            gzip off;
        }
    }

然后Nginx到cockpit之间不搞加密,编辑/etc/cockpit/cockpit.conf

[WebService]
AllowUnencrypted = true
ProtocolHeader = X-Forwarded-Proto
Origins = https://pcvm00:50505 wss://pcvm00:50505
ForwardedForHeader = X-Forwarded-For

记得防火墙拦一下别让人直接访问Cockpit的9090端口。

然后重启Nginx和Cockpit:

systemctl restart nginx.service
systemctl restart cockpit.service

客户端

导入PFX格式的客户端证书到Windows,并信任自签的根证书,登录时选择自己的证书即可访问cockpit界面。