相关参数
-C 压缩数据传输
-f ssh 连接成功后,转入后台运行(关闭连接时可以使用 kill )
-N 不打开远程 shell
-T 不为这个连接分配 tty(与 -N 一起使用,表示这个 ssh 只用来传递数据,不执行远程操作)
-g 允许打开的端口让其他主机访问(见本地转发)
-L 本地端口转发(local)
-R 远程端口转发(remote)
-D 动态转发(dynamic)
-p 指定 ssh 端口
Local Forwarding
将本地主机某个端口流量转发到远程主机的指定端口
host1(local-host)<----->host2(middle-host)<----->host3(target-host)
host1 是本地主机,host3 是远程主机(host1 与 host3 无法连通),host2 可以同时连接 host1 和 host3;通过 host2,连接 host1 和 host3。
- host1: local-host
- host2: middle-host
- host3: target-host
在 local-host 上执行:
$ ssh -L [bind_local_address]:<local-host-port>:<target-host>:<target-host-port> <middle-host>
指定本地 ssh client 监听 local-host-port,通过 middle-host 的 ssh server 将所有数据,转发到 target-host 的 target-host-port
比如在 host1 上执行:
$ ssh -L 1080:host3:21 host2
$ ftp localhost:1080
当使用 ftp 请求 localhost:1080 时,请求内容会通过 host2 转发给 host3:21(21为ftp默认端口),也就是说,使用 ftp 访问 localhost:1080 就等同与访问 host3:21。对应的连接关系如下:
host1(local-host) host2(middle-host) host3(target-host)
1080 - ssh client <-----> ssh server <-----> 21
在选择端口号时要注意非管理员帐号是无权绑定 1-1023 端口的,所以一般是选用一个 1024-65535 之间的并且尚未使用的端口号即可
示例:反向代理
服务内网中有 2 台机器:
- host3:只能内外访问,运行 tcp 服务,端口 5432
- host2:和 host3 在同一内网下,同时有自己的外网IP
内网外有一台机器:
- host1:host1 与 host3, host2 不在同一内网中,host1 上的应用需要访问 host3 上的服务。
方法1:在 host2 上执行(必须加 -g
参数才能使 ssh client 监听的端口可以被其他主机访问):
$ ssh -C -f -N -g -L 5432:host3:5432 root@host2
这时可以在 host1 上访问 host2:5432。对应连接关系如下:
host1(local-host) <-- host2(middle-host) host3(target-host)
\---> 5432 - ssh client <--> ssh server <-----> 5432
方法2:在 host1 上执行:
$ ssh -C -f -N -L 5432:host3:5432 root@host2
这时可以在 host1 上访问 localhost:5432。对应连接关系如下:
host1(local-host) host2(middle-host) host3(target-host)
5432 - ssh client <-----> ssh server <-----> 5432
Remote Forwarding
host1(remote-host)<------host2(local-host)<----->host3(target-host)
当 host1 无法连接 host2 和 host3,而 host2 可以连接 host1 与 host3 时,可以在 host2 上使用远程端口转发来完成 host1 和 host3 的连接。
- host1: remote-host
- host2: local-host
- host3: target-host
在 local-host 上执行:
$ ssh -R <remote-host-port>:<target-host>:<target-host-port> <remote-host>
使 remote-host 监听 remote-host-port 端口,然后将所有数据经由 local-host 转发到 target-host 的 target-host-port
比如在 host2上执行:
$ ssh -R 1080:host3:21 host1
在 host1 上执行:
$ ftp localhost:1080
在 host1 上使用 ftp 请求 localhost:1080 时,请求内容会通过 host2 转发到 host3:21
对应连接关系:
host1(remote-host) host2(local-host) host3(target-host)
1080 - ssh server <-----> ssh client <-----> 21
示例:内网穿透
访问内网中 windows 远程桌面:
- 内网中 windows 主机开启远程桌面访问,端口 3389
- 有 ssh 登录权限的一台拥有外网 IP 的主机,外网IP 152.32.253.99
-
在内网 windows 主机上执行:
$ ssh -R 3389:127.0.0.1:3389 ubuntu@152.32.253.99
- 其他机器可以通过 152.32.253.99:3389 连接远程桌面
对应的连接关系如下:
other host <--- ubuntu@152.32.253.99 windows
\--> 3389 - ssh server <------> ssh client - 3389
此时 local-host 与 target-host 是同一台机器,内网中的 windows
ssh 远程转发默认只能绑定远程主机的本地端口,即127.0.0.1
,如果想监听来自所有主机的连接,需要修改远程主机的 /etc/ssh/sshd_config
配置文件,将 GatewayPorts
项的对应值改为 yes
,重启 ssh 后生效。
动态转发
动态转发不指定目标 host 与目标端口:
$ ssh -D <local-port> <middle-host>
比如:
$ ssh -D 1080 middle-host
指定本地 ssh client 监听 1080 端口,将本地 1080 端口的所有请求通过 middle-host 的 ssh server 发送到目标机器端口,之后我们可以使用 localhost:1080 作为正常的 socks5 代理来使用
保持持久连接
client 端配置 /etc/ssh/ssh_config
修改以下内容:
Host *
# tcp 长连接
TCPKeepAlive yes
# 客户端每隔 60 秒向服务端发送空数据
ServerAliveInterval 30
server 端配置 /etc/ssh/sshd_config
修改以下内容:
# 服务端每隔 60 秒向客户端发送一个空数据包
ClientAliveInterval 60
# 服务端最多发送 720 次,60 * 720 秒 = 12 小时
ClientAliveCountMax 1
参考
[SSH 端口转发教程 | 三点水](https://lotabout.me/2019/SSH-Port-Forwarding/) |
- older
- Newer