使用SSH反向隧道进行内网穿透

这篇文章主要介绍了如何利用SSH 反向隧道穿透NAT,并演示了如何维持一条稳定的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

这里默认你的系统init 程序为systemd,如果你使用其他的init 程序,如果没有特殊理由还是换到一个现代化的GNU/Linux 系统吧……

SSH 反向隧道

这种手段实质上是由B 向A 主动地建立一个SSH 隧道,将A 的6766 端口转发到B 的22 端口上,只要这条隧道不关闭,这个转发就是有效的。有了这个端口转发,只需要访问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 userb @localhost

隧道的自动建立

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

“打洞”

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

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

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

        
        
1
        
        
GatewayPorts yes

然后重启sshd

        
        
1
        
        
A $ sudo systemctl restart sshd

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

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

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

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

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

最终的解决方案

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

首先打开A 上sshd 的GatewayPorts 开关,并重启sshd(如有需要)。

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

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

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

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

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

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

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

在B 上让network-online.target 生效:

        
        
1
        
        
B $ systemctl enable NetworkManager- wait-online

如果你使用systemd-networkd,你需要启用的服务则应当是systemd-networkd-wait-online 。

然后设置该服务自动启动:

        
        
1
        
        
B $ sudo systemctl enable autossh

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

        
        
1
        
        
B $ sudo systemctl start autossh

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

        
        
1
        
        
A $ ssh -p 6766 userb @localhost

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

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

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

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

假设C 是你家中的电脑,A 是你的VPS,B 是你公司的电脑。如果你这样做了,那么为浏览器设置端口为7677 的sock4 本地(localhost)代理后,你就可以在家里的浏览器上看到公司内网的网页。

### 什么是SSH内网穿透 SSH内网穿透是一种技术手段,允许外部网络访问位于内部局域网中的设备和服务。这种技术通常用于远程管理和数据传输场景下,解决因防火墙或路由器限制而导致无法直接访问目标主机的问题。 --- ### 使用Cpolar实现Linux系统的SSH内网穿透 对于基于Linux的操作系统,可以利用Cpolar工具快速完成SSH内网穿透配置。以下是具体说明: #### 安装Cpolar并创建公网SSH连接地址 在Linux环境中安装Cpolar后,可以通过其内置功能生成一个可被外网访问的SSH连接地址[^1]。此过程涉及启动Cpolar客户端并与服务器建立隧道连接。 #### JuiceSSH进行公网远程连接 JuiceSSH是一款适用于Android平台的SSH客户端软件,在完成了上述步骤之后,用户能够借助该应用经由所生成的公有IP端口组合来登录到自己的Linux机器上。 #### 固定SSH公网地址及测试 为了保障每次重启服务或者更换会话时仍能保持一致性的接入路径,则需进一步设置固定的映射关系,并执行必要的功能性验证操作以确认一切正常运作。 --- ### Windows环境下SSH内网穿透方案 同样地,在微软Windows操作系统里也可以达成相似效果——即让外界得以穿越NAT层抵达个人计算机上的资源位置处。 #### 启用与检验本地SSH服务能力 先要确保本机已开启支持OpenSSH协议的服务组件;接着运用标准命令行界面来进行初步的功能性检测,比如尝试ping回环地址localhost(127.0.0.1),以此判断当前状态是否满足预期需求[^2]。 #### Cpolar部署于Winows之上 紧接着按照官方指引下载对应版本号的exe文件包,依照提示完成整个安装配对流程直至成功上线运行为止。此时应该可以看到一条新的tcp类型的转发记录显示出来代表已经建立了通往互联网的大门入口通道。 #### 测试来自远方地点发起的安全shell请求能否顺利到达指定的目标节点那里去。 最后一步就是实际动手去做一下完整的端到端贯通实验啦! 只需要用任意一款兼容posix接口规范定义下的图形化前端程序像Putty那样东西就可以轻松搞定全部事情咯. --- ### 利用Autossh增强稳定性 考虑到长时间维持稳定可靠的链接可能存在挑战, 推荐采用autossh替代普通的ssh指令下达形式来做同样的工作内容. 它具备自动重连机制以及心跳探测特性等功能优势可以帮助我们更好地应对可能出现的各种异常状况. 命令样例如下所示: ```bash autossh -M 0 -L 443:127.0.0.1:332 root@[ssh_server] -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" ``` 这里设置了每隔三十秒钟发送一次探针信号给远端伙伴告知自己还活着; 如果连续三次都没有收到回应就会触发重新构建关联动作直到恢复正常通讯联系为止.[^3] --- ### Frp作为另一种选择 Frp (Fast Reverse Proxy) 是另一个非常流行且高效的反向代理解决方案之一, 特别适合用来处理复杂的多业务场景下的流量调度问题. 它的架构设计清晰明了易于理解和掌握, 并提供了丰富的参数选项让用户可以根据实际情况灵活调整优化性能表现. ![frp_http_and_ssh](https://example.com/frp-http-and-ssh.png) 以上图片展示了http和ssh两种模式下的基本原理框架图解说明文档资料来源出处标记如下:[^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值