[分享] SSH和Git共享22端口,适用于docker或者frp转发等

先说下我的使用场景:

  1. 我有一台跑在腾讯云上的VPS,就是此博客系统所在的机器,这台机器是有公网IP的
  2. 在我家里的内网,有一台4核16G的小型服务器,没有公网IP,运行Proxmox VE虚拟了各种服务,其中包括Gitea
  3. 我通过frp转发暴露内网的Gitea到公网
  4. 在这之前我一直使用HTTP协议上传或者下载代码,现在觉得太麻烦想用SSH协议

如果你跟我的场景类型,此文很适合你,如果你是同一台机器上docker宿主机之间22端口共享问题,文末官方文档更适合你。

本文也是参考了文末官方文档的实现,但是有部分不太一样。

安装Gitea

参考官方从二进制安装安装,同时配置service运行,这里不多说。

但是建议使用git用户安装,这样运行目录就是 /home/git/gitea,后文会按照这个路径来说明。

配置frp转发

frpc.ini添加如下配置,分别转发HTTP协议和SSH协议:

[home.gitea]
type = http
local_ip = 192.168.1.103
local_port = 3000
custom_domains = git.fengqi.me
use_compression = true

[home.gitea.ssh]
type = tcp
local_ip = 192.168.1.103
local_port = 22
remote_port = 44322
use_compression = false

创建新的 SSH 密钥对

在有公网IP的机器上执行命令:

sudo -u git ssh-keygen -t ed25519 -C "Gitea Host Key"

连续回车,使用默认的文件名,无密码,生成完成后,复制 ~/.ssh/id_ed25519.pub 的内容,添加到内网机器的/home/git/.ssh/authorized_keys内。

注:如果您使用的是不支持 Ed25519 算法的旧系统,请使用以下命令:
sudo -u git ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
可以把4096改完3072或者2048,降低加密强度。

如果你的公网机器上没有git用户,需要执行一下命令创建:

sudo adduser --disabled-login --gecos 'Gitea' git

创建 gitea 文件

在有公网IP的机器上创建/home/git/gitea文件,并写入如下内容:

ssh -p 44322 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"

里面的端口ip改为你实际运行Gitea的机器的,并执行 chmod +x /home/git/gitea 给予可执行权限。

同步SSH公钥

复制内网运行Gitea机器上/home/git/.ssh/authorized_keys的全部command="/home/git/gitea开头的内容,添加到有公网IP机器的/home/git/.ssh/authorized_keys内,注意不要覆盖你原有的内容,是新增。

这里需要注意的是,官方的文档docker是和宿主机共享一份authorized_keys文件,如果在Gitea的Web界面添加SSH公钥,宿主机也能使用最新的。

但是本文的方案是分离的,所以需要自己想办法同步公网机器和内网Gitea机器的authorized_keys文件,否则新增的用户SSH认证会失败。

如果你是和我一样自用,不对外公开,那手动处理就行了。

测试

理论上这个时候你已经可以使用git协议上传和下载代码了

如果你碰到如下报错:

ssh: connect to host 127.0.0.1 port 44322: Connection refused

可以尝试在有公网IP的机器上执行 ssh -p 44322 git@127.0.0.1 来确认frp转发是否配置正常

如果你碰到如下报错:

Gitea: Internal Server Error
fatal: Could not read from remote repository.

请确认在有公网IP上生成的密钥对的公钥是否添加到内网机器上

如果你碰到如下报错:

Permission denied (publickey,password).
fatal: Could not read from remote repository.

请确认内网机器和有公网IP的机器的authorized_keys内容是否同步,留意key-1,key-2,key-3。。。的对应是否正确

原理:

  1. 生成的新密钥对是用于公网机器到内网机器的SSH认证,走的是frp开辟出来的通道
  2. 公网机器会通过这个通道把GitSSH命令就是SSH_ORIGINAL_COMMAND转发到内网
  3. 需要同步公网和Gitea的key的原因是,git操作首先是需要和公网IP的机器进行SSH认证,通过后才能触发脚本转发到frp开辟的通道,所以其实会有两次SSH认证

参考文档

SSH 容器直通

标签: git, ssh, docker, frp

添加新评论