FavoriteLoading
0

使用SSH反向隧道实现内网穿透

不管是在渗透或者日吃的远空中,内网穿透都是一个重要的环节,我们本身及其分配到的内网IP通过外网是无法进行访问的,所以本文将会告诉你如何使用Linux的SSH反向隧道进行内网穿透。

假设有机器A 和B,A 有公网IP,B 位于NAT 之后并无可用的端口转发,现在想由A 主动向B 发起SSH 连接。由于B 在NAT 后端,无可用公网IP + 端口 这样一个组合,所以A 无法穿透NAT,本文应对的就是这种情况。也是大多数人遇到的。

我们先假设如下几台机器:

机器代号 机器位置 地址 账户 ssh/sshd端口 是否需要运行sshd
A 位于公网 a.site usera 22
B 位于NAT之后 localhost userb 22
C 位于NAT之后 localhost userc 22

SSH 方向隧道连接

这种手段是指上是由B向A主动地建立一个SSH隧道,将A的6766端口转发到B到端口上,只要这条隧道不关闭,这个转发就是有效的。只需要访问A的6766端口反向连接B即可。

首先在B上建立一个SSH隧道,将A的6766端口转发到B的22端口上:

1 B $ ssh -p 22 -qngfNTR 6766:localhost:22 usera@a.site

然后在A上利用6766反向SSH到B

1 A $ ssh -p 6766 userb@localhost

要做的事情其实就是这么简单。

 

      隧道的维持

稳定性维持

 

然而不幸的是SSH连接是会超时关闭的,如果连接关闭,隧道无法维持,那么A就无法利用反向隧道穿透B所在的NAT了,为此我们需要一种方案来提供一条稳定的SSH反向隧道。

一个最简单的方法就是autossh,这个软件会在超时之后自动建立SSH隧道,这样就解决了隧道的稳定性问题,如果你使用了Arch  Linux,你可以这样获得它:

1 $ sudo pacman -S autossh

 

下面在B上做之前类似的事情,不同的是该隧道会由autossh来维持:

1 B $ autossh -p 22 -M 6777 -NR 6766:localhost:22 usera@a.site

-M参数指定的端口用来监听隧道的状态,与端口转发无关。

之后你可以在A上通过6766端口访问B了:

1 A $ ssh -p 6766 user@localhost

隧道的自动建立

然而这又有了另外一个问题,如果B 重启隧道就会消失。那么需要有一种手段在B 每次启动时使用autossh 来建立SSH 隧道。很自然的一个想法就是做成服务,之后会给出在systemd 下的一种解决方案。

“打洞”

之所以标题这么起,是因为自己觉得这件事情有点类似于UDP 打洞,即通过一台在公网的机器,让两台分别位于各自NAT 之后的机器可以建立SSH 连接。

下面演示如何使用SSH 反向隧道,让C 连接到B。

首先在A 上编辑sshd 的配置文件/etc/ssh/sshd_config,将GatewayPorts 开关打开:

1 GtaewayPorts yes

然后重启ssh

1  A $ sudo systemct1 restart sshd

然后在B上对之前用到的autossh指令略加修改:

1 B $ autossh -p 22 -M 6777 -NR '*:6766:localhost:22' user@a.site

之后再C上利用A的6766端口SSH连接到B:

1 C $ ssh -p 6766 user@a.site

至此你轻而易举的穿透了两层NAT

最终解决方案

整合一下前面提到的,最终解决方案如下:

首先打开A上的sshd的GatewayPorts开关,并重启sshd。

然后再B上新建一个用户autossh,根据权限最小化思想,B上的autossh服务讲义autossh用户身份运行,尽可能地避免出现安全问题:

1 B $ sudo useradd -m autossh
2 B $ sudo passwd autossh

紧接着B上为autossh用户创建SSH密钥,并上传到A:

1 B $ su - autossh
2 B $ ssh-keygen -t ;rsa' -C 'autossh@B'
3 B $ ssh-copy-id user@a.site

注意该密钥不要设置密码,也就是运行ssh-keygen 指令时尽管一路回车,不要输入额外的字符。

然后在B 上创建以autossh 用户权限调用autossh 的service 文件。将下面文本写入到文件/lib/systemd/system/autossh.service,并设置权限为644:

1 [Unit]
2 Description=Auto SSH Tunnel
3 After=network-online.target
4 [Service]
5 User=autossh
6 Type=simple
7 ExecStart=/bin/autossh -p 22 -M 6777 -NR '*:6766:localhost:22' usera@a.site -i /home/autossh/.ssh/id_rsa
8 ExecReload=/bin/kill -HUP $MAINPID
9 KillMode=process
10 Restart=always
11 [Install]
12 WantedBy=multi-user.target
13 WantedBy=graphical.target

在B上设置network-online.target生效:

1 B $ systemctl enable NetworkManager-wait-online

如果你使用systemd-networkd,你需要重启服务则应当是systemd-networkd-wait-online。然后设置该服务自动启动:

1 B $ systemctl enable autossh

如果你愿意,在这之后可以立即启动它:

1 B $ systemctl start autossh

然后你就可以在A上使用这条反向隧道穿透B所在的NAT SSH连接到B:

1 C $ ssh -p 6766 user@localhost

或者是在C上直接穿透两层NAT SSH连接到B:

1 C $ ssh -p 6766 user@a.site

如果你对ssh足够熟悉,你可以利用这条隧道做更多的事情,例如你可以再反向连接时指定动态端口转发:

1 C $ ssh -p 6766 -qngfNTD 7677 user@site.a

加入C是你家中的电脑,A是你的VPS,B是你公司的电脑。照以上做的话,那么浏览器端口设置为7677的sock4本地(localhost)代理后,你就可以在家中浏览器上看到公司的网页。
家有一些其他的等等用处就不多说了,各位都知道。。。。。