使用SSH反向隧道实现内网穿透
没有公网 IP?内网服务器成笼中凤凰?果断穿透一波! 手头上有三台机器, 记号如下:
记号 | 位置 | 地址 | 账户 |
---|---|---|---|
A | 位于公网 | a.site | usera |
B | 位于 NAT 之后 | localhost | userb |
C | 位于 NAT 之后 | localhost | userc |
操作
- 在机器 A 上:
- 设置
sshd
设置文件/etc/ssh/sshd_config
:GatewayPorts yes
sudo systemctl restart sshd
- 设置
-
在机器 B 上: 创建 SSH 密钥, 上传至 A:
1
2ssh-keygen -t 'rsa'
ssh-copy-id usera@a.site -
-
如果仅作测试, 直接键入命令
1
autossh -M 6777 -NR 6766:localhost:22 usera@a.site -i /path/to/id_rsa
即可, 但该命令会在前端等待. 如果需要不间断运行地置于后台, 可使用
nohup
命令:1
nohup autossh -M 6777 -NR 6766:localhost:22 usera@a.site -i /path/to/id_rsa >/dev/null 2>&1 &
autossh
再次开启 (所以可能导致kill
不掉进程), 如果改为 0 则表示没有守护进程. - 如果希望作为系统服务并开机启动, 需进行如下操作:
-
编辑文件
autossh.service/etc/systemd/system/autossh.service
,1
2
3
4
5
6
7
8
9
10[Unit]
Description=autossh ssh
After=network-online.target
[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -o "ExitOnForwardFailure=yes" -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -NR 6766:localhost:22 usera@a.site -i /path/to/id_rsa
[Install]
WantedBy=multi-user.target -
一通令之生效的操作:
1
2
3
4sudo systemctl daemon-reload
sudo systemctl enable autossh
sudo systemctl start autossh
sudo systemctl status autossh
-
*.service
文件中需要写绝对路径systemctl enable
表示设置服务为自动启动
-
开耍
- A 连 B:
ssh -p 6766 userb@localhost
- C 连 B:
ssh -p 6766 userb@a.site
- 反向连接时指定动态端口转发(机器 C):
ssh -p 6766 -qngfNTD 7677 userb@a.site
问题
- 防止超时断开:
- 在 B 和 C 的
/etc/ssh/ssh_config
后面加上:ServerAliveInterval 60
- 在 A 机的
/etc/ssh/sshd_config
后面加上:ClientAliveInterval 60
- 在 B 和 C 的
- 少数情况下, 问题会出在 ssh 的认证上, 可能需要下列操作:
- 修改文件
/etc/ssh/ssh_config
:1
2
3GSSAPIAuthentication no
GSSAPIDelegateCredentials no
StrictHostKeyChecking no
- 修改文件
除了利用 autossh
作为反向代理工具, 强大的 ssh
自身就可以实现正向代理以及反向代理. 下面摘自 SSH隧道与端口转发内网穿透.
-L port:host:hostport
: 将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 本地机器上分配了一个socket
侦听port
端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和host
的hostport
端口建立连接. 可以在配置文件中指定端口的转发. 只有root
才能转发特权端口. IPv6 地址用另一种格式说明:port/host/hostport
-R port:host:hostport
: 将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 远程主机上分配了一个socket
侦听port
端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和host
的hostport
端口建立连接. 可以在配置文件中指定端口的转发. 只有用root
登录远程主机才能转发特权端口. IPv6 地址用另一种格式说明:port/host/hostport
-D port
: 指定一个本地机器「动态的」应用程序端口转发. 本地机器上分配了一个socket
侦听port
端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持SOCKS4
协议, 将充当SOCKS4
服务器. 只有root
才能转发特权端口. 可以在配置文件中指定动态端口的转发-p
: 指定登录端口-f
: 后台认证用户 / 密码, 通常和-N
连用, 不用登录到远程主机-N
: 不执行远程命令-q
: 进入安静模式-C
: 压缩数据传输-g
: 在-L/-R/-D
参数中, 允许远程主机连接到建立的转发的端口, 如果不加这个参数, 只允许本地主机建立连接
常用的 SSH 隧道操作:
- 正向代理:
ssh -C -f -N -L listen_port:DST_Host:DST_port user@Tunnel_Host
- 反向代理:
ssh -C -f -N -R listen_port:DST_Host:DST_port user@Tunnel_Host
- 动态转发:
ssh -C -f -N -D listen_port user@Tunnel_Host
为保持长时间连接, 同 autossh
的参数, ssh
可附加的参数有: -o TCPKeepAlive=yes
, -o ServerAliveInterval=30
, -o ServerAliveCountMax=3
等.