通过ssh实现端口的反向转发,可以通过ssh实现内网机器直接在公网上被ssh访问
一、基本情况
- 环境介绍:
– hostA 192.168.20.1(家用主机)
– hostB 139.224.10.45 (阿里云服务器)
- 目的:为了实现在外网能够主动访问到家用网络中的个人电脑。
二、ssh命令使用
- ssh相关参数 -D [bind_address:]port
指定一个本地动态应用层端口做转发端口。工作方式是分配一个套接字监听在此端口,当监听到此端口有连接时,此连接中的数据将通过安全隧道转发到server端,server端再和目的地(端口)建立连接,目的地(端口)由应用层协议决定。目前支SOCK4和SOCK5两种协议,并且SSH将扮演SOCKS服务端角色。
只有root用户可以开启特权端口。动态转发端口也可以在配置文件中指定。
默认情况下,转发端口将绑定在GatewayPorts指令指定的地址上,但是可以显式指定bind_address,如果bind_address设置为”localhost”,则转发端口将绑定在回环地址上,如果bind_address不设置或设置为”*”,则转发端口绑定在所有网路接口上。
-E log_file
将debug日志写入到log_file中,而不是默认的标准错误输出stderr。
-f 请求ssh在工作在后台模式。该选项隐含了”-n”选项,所以标准输入将变为/dev/null。
-G 使用该选项将使得ssh在匹配完Host后将输出与之对应的配置选项,然后退出
-g 允许远程主机连接到本地转发端口上。
-N 明确表示不执行远程命令。仅作端口转发时比较有用。
-q 静默模式。大多数警告信息将不输出。
-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket
对远程(server端)指定的TCP端口port的连接都就将转发到本地主机和端口上,工作方式是在远端(server)分配一个套接字socket监听TCP端口。当监听到此端口有连接时,连接将通过安全隧道转发给本地,然后从本地主机建一条到host:hostport的连接。端口转发也可以在配置文件中指定。只有root用户才能转发特权端口(小于1024)。
默认远程(server)套接字被绑定在回环地址上。但是,显式指定的bind_address可以用于绑定套接字到指定的地址上。如果不设置bind_address或设置为”*”则表示套接字监听在所有网络接口上。
只有当远程(server)主机的GatewayPorts选项开启时,指定的bind_address才能生效。(见sshd_config(5))。
如果port值为0,远程主机(server)监听的端口将被动态分配,并且在运行时报告给客户端。 - 具体命令
ssh -fNR dport:localhost:sport user@dip -p port
ssh -fNR 4444:localhost:22 root@10.21.0.81 -p 256
- 解析:
- 功能:在远程主机10.21.0.81(dip)上打开4444(dport)端口,远程主机可通过访问本机的4444端口访问localhost源主机的对应端口
- 详解:
- -f 用于使给命令保持后台运行,-N不向目标发送任何命令
- -R [bind_address:]port:host:hostport 格式: 远端地址:希望远端开放的端口:本机地址:本机ssh的端口 。远端地址可以省略,因为后面会有远端的访问地址。远端地址端口、本地地址端口都可以用套接字代替。这个-R参数在连接远端机器的同时,对远端机器做了这样的请求:在localhost端口4444上监听,并将在此接收到的数据包通过我们这个ssh连接转发给我。远端按照该请求执行是ssh协议允许的,在远端机器上4444端口监听的仍然是sshd进程,它可以决定将数据包用sshd下的哪个线程进行处理。当然,此后发往远端机器上4444端口的数据都会被sshd进程收到,并由本地与远端的ssh通道发送给本地机器。另外,本地机器收到这个数据后,认为这个数据是发给22号端口的,即本地机器上的ssh服务。整个过程都是在ssh服务框架下完成的。
三、实验
- 主机A:Centos7.6 IP:192.168.44.17 本地主机主机B:Ubuntu18 IP:136.22.10.4 ssh端口:666 远程主机
- 在A上执行命令
ssh -fNR 4444:localhost:22 root@136.22.10.4 -p666
- 查看B上的端口是否打开
ss -ntlp
- 在B上ssh测试
ssh root@127.0.0.1 -p4444
- 在A上执行命令
- 注意事项
- 该操作只允许从本机访问127.0.0.1地址的对应端口实现
- 关闭连接,通过kill掉远程对应端口下的sshd进程
四、扩展
4.1 实现第三方主机直接访问本地主机
4.1.1 通过iptables转发实现,参考命令:
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 4444 -j DNAT --to-destination 127.0.0.1:4444
访问远程主机的4444端口时,远程主机会自动转发到本机127.0.0.1的4444端口。
注意:要实现转发到本机地址的端口,需手动开启本地路由,参考命令:
echo 1 > /proc/sys/net/ipv4/conf/all/route_localnet
4.1.2 配置服务器端ssh
修改公网主机 B 的 SSH 配置文件/etc/ssh/sshd_config
GatewayPorts yes
这样可以把监听的端口绑定到任意 IP 0.0.0.0 上,否则只有本机 127.0.0.1 可以访问。
重启 sshd 服务
sudo service sshd restart
4.2 实现其他端口的转发
– 上述ssh命令,将本机端口改为其他的服务端口时,依然能够生效,且能够实现端口的反向转发。例:
ssh -fNR 4444:localhost:80 root@136.22.10.4 -p666 #如果本地机器有http服务,且监听在80端口。那么执行该命令后,也可通过访问远端的4444端口来访问本机的http服务,即实现了反向的端口转发
4.3 利用 AutoSSH 实现稳定持久端口转发
在内网主机 A 上先安装autossh,利用 AutoSSH 建立一条 SSH 隧道
autossh -M 4010 -NR 80:localhost:4000 username@xxx.xxx.xxx.xxx (-p xxxx)
参数解释:
- “-M 4010”意思是使用内网主机 A 的 4010 端口监视 SSH 连接状态,连接出问题了会自动重连
- “ -N”意思是不执行远程命令
- “-R”意思是将远程主机(公网主机 B)的某个端口转发到本地指定机器的指定端口
代码解释:
- “80:localhost:4000”意思是将内网主机 A 的 4000 号端口转发至公网主机 B 的 80 号端口上
- “username@xxx.xxx.xxx.xxx”意思是公网主机 B 的用户名和 IP
- “-p xxxx”意思是公网主机 B 的 SSH 端口,如果是默认的 22 号端口,则可以不输入.
- 总结
- 该功能主要用于,无法被外部网络直接访问的主机,通过外部服务器(跳板机)进行访问,且实现端口转发等功能。