ssh 常用的有三种端口转发功能,下面记录一下这三种转发都能做些什么。
动态端口转发
一条命令实现 socks5://127.0.0.1:<port>
代理:
ssh -p <remote_ssh_port> -fND 127.0.0.1:<proxy_port> <remote_user>@<remote_host>
远程端口转发
场景是有一台内网服务器 machine1,一台公网服务器 machine2,并且 machine1 不能通过内网直接访问 machine2,但是 machine2 可以访问 machine1。现在需要从外网的 machine3 访问 machine1。
我们可以使用 ssh 的远程端口转发功能来实现 machine3 通过 machine2 来访问 machine1。
ssh server 配置
首先需要在 machine2 上的 /ect/ssh/sshd_config
设置
AllowTcpForwarding yes # 允许 TCP 转发
GatewayPorts yes # 允许远程主机连接转发的端口
为了安全性,最好只使用密钥验证:
PubkeyAuthentication yes # 使用密钥验证
PasswordAuthentication no # 禁用密码验证
使用不同的 ssh key
为了安全,这里使用单独的 ssh key 来访问 machine1。
首先生成新的 key:
ssh-keygen -C "external_visitor" -f ~/.ssh/id_ed25519_external_visitor
ed25519 是目前 ssh 使用的默认密钥算法。可以使用 -t
来指定想要使用的密钥算法。
然后在 machine3 上的 ~/.ssh/config
中添加配置,指定访问 machine2 的时候使用的 key:
Host my_internal_server
HostName machine2
User ouonline
IdentityFile ~/.ssh/id_ed25519_external_visitor
别忘了把新的 public key ~/.ssh/id_ed25519_external_visitor.pub
加到 machine1 的 ~/.ssh/authorized_keys
中。注意这里不需要把 public key 加到 machine2 中,这样虽然我们通过 machine2 能登录 machine1,但是我们仍然不能登录 machine2。
映射端口
假设我要通过 machine2 的 2222 端口来访问 machine1 的 22 端口,则需要在 machine1 上执行
ssh -o ServerAliveInterval=3 -o ExitOnForwardFailure=yes -fNR *:2222:machine1:22 machine2_user@machine2
这里的 -f
选项表示后台执行;-N
表示不执行命令,只做端口转发;-R
表示将任意来源访问 machine2 的 2222 端口的 tcp 流量转发到 machine1 的 22 端口。多加的两个 -o
选项是为了在 ssh 快速发现抖动或掉线。
ssh 可能会因为网络抖动或者空闲超时等原因中断,可以加一个 while 循环重连:
while true; do
ssh ...
sleep 2
done
现在可以在 machine3 上登录 machine1 了:
ssh -p 2222 machine1_user@machine2
注意这里用的是 machine1 上的用户名。
本地端口转发
简单说就是将远程内网服务暴露到本地。还没用到,以后补充。
这种网络环境下面是不是用mosh转发好一点?
我会尽量用系统自带的工具。反向代理的功能很多软件都有,像 frp,nginx 都可以,在我的使用场景 ssh 就足够了。