如何配置GitLab Nginx实现SSH通过443端口代理并解决400错误
核心问题
你当前使用的是Nginx HTTP层配置处理443端口流量,而通过HTTPS端口转发的SSH流量不属于HTTP协议,Nginx HTTP模块无法解析非HTTP格式的请求,因此返回400 Bad Request错误。
修复方案
推荐使用Nginx ngx_stream_ssl_preread 模块实现基于SNI的流量分发,将gitssh.mysite.com的443端口流量直接转发到GitLab SSH服务,其他域名的HTTPS流量照常走业务逻辑,和 GitHub ssh.github.com 的实现逻辑一致。
步骤1:新增Stream层配置
编辑GitLab Nginx主配置文件(默认路径/var/opt/gitlab/nginx/conf/nginx.conf),在http块外部添加如下配置:
stream { log_format ssh_proxy '$remote_addr [$time_local] ' '$ssl_preread_server_name $protocol $status ' '$bytes_sent $bytes_received $session_time'; access_log /var/log/gitlab/nginx/ssh_proxy_access.log ssh_proxy; error_log /var/log/gitlab/nginx/ssh_proxy_error.log; # 开启SSL预读获取SNI域名 ssl_preread on; # 后端服务定义 upstream gitlab_ssh { server 127.0.0.1:22; # 替换为你实际的GitLab SSH监听端口 } upstream gitlab_https { server 127.0.0.1:8443; # 原有HTTPS服务改为本地8443端口监听 } # 根据SNI域名分发流量 map $ssl_preread_server_name $backend { gitssh.mysite.com gitlab_ssh; git.mysite.com gitlab_https; # 其他需要走HTTPS的域名可在此处追加 } server { listen 443 reuseport; listen [::]:443 reuseport; proxy_pass $backend; proxy_timeout 1h; # 适配大文件Git传输的长连接需求 } }
步骤2:修改原有HTTP层配置
将你原有配置中HTTPS服务的监听端口从*:443改为127.0.0.1:8443,无需对外暴露:
# 修改前:listen *:443 ssl http2; # 修改后: listen 127.0.0.1:8443 ssl http2;
步骤3:调整SSH客户端配置
修改本地~/.ssh/config的对应规则,确保HostName匹配SNI分发规则:
Host git.mysite.com HostName gitssh.mysite.com User git Port 443 ProxyCommand /usr/bin/corkscrew 127.0.0.1 3129 %h %p
验证与排查
- 配置修改后执行
gitlab-ctl restart nginx重启服务 - 本地执行
nc gitssh.mysite.com 443,正常会返回SSH-2.0-OpenSSH_xxx的SSH服务标识 - 若连接失败可查看
/var/log/gitlab/nginx/ssh_proxy_error.log定位具体问题
内容的提问来源于stack exchange,提问作者weera
相关产品推荐
相关产品推荐

