ssh反向连接内网主机

2023-05-26,,

什么是 Serveo

Serveo 是一个免费的内网穿透服务,Serveo 可以将本地计算机暴露在互联网上,官方声称其为 Ngrok 的绝佳替代品。

Serveo 其最大优点是使用现有的 SSH 客户端,无需安装任何客户端软件,即可完成端口转发。

Serveo 工作原理很简单:当用户通过 SSH 连接到 Serveo 时会与该网站建立一个远程代理,Serveo 随后会生成一个 公共 URL,任何人都可以通过这个 URL 访问你的本地计算机。

项目地址: https://serveo.net

autossh使用文档:https://www.everythingcli.org/ssh-tunnelling-for-fun-and-profit-autossh/

使用 Serveo

Serveo 的使用非常简单,只需要可以使用 SSH 客户端并且能连接到互联网的任意系统都行。比如:LinuxWindowsMacOS 等系统,就算是 AndroidiOS 也同样没问题。下面我们来看几个最常用的使用实例:

1、开放本地服务到公网

将一个本地应用的 8080 端口映射到公网中。(当然也可以开放本地局域网的其它服务,替换“localhost:端口号”即可,只是毕竟通过隧道转发的原因,速度会相比慢一些)

# 如果要转发其它端口,只需替换端口为其它就可以了
$ ssh -R 80:localhost:8080 serveo.net
Hi there
Forwarding HTTP traffic from https://heryum.serveo.net
Press g to start a GUI session and ctrl-c to quit.

SSH 连接成功后,会随机生成一个 serveo.net 二级域名。随后你就可以使用浏览器访问这个随机生成的二级域名 heryum.serveo.net 间接访问到本地计算机 8080 端口上的服务了。

SSH 初次和一个新服务器建立连接时会有提示,直接选择 yes 即可。

如果你不想使用随机域名,想指定一个固定的二级域名也是可以的。

# 这里指定为 wjoyxt.serveo.net,可以根据自身情况进行替换
$ ssh -R wjoyxt::localhost: serveo.net
Hi there
Forwarding HTTP traffic from https://wjoyxt.serveo.net
Press g to start a GUI session and ctrl-c to quit.
... # 上面的域名是简写的,你也可以写出完整的域名。
$ ssh -R wjoyxt.serveo.net::localhost: serveo.net

SSH 连接成功后,此时就可以在公网上使用 ywzm.serveo.net 访问到你本地计算机 8080 端口的服务了。

上面的例子中,我们转发的是 HTTP 服务。如果你需要转发的是 TCP 服务,又应该怎么做呢?其实方法也很简单,同样只需设置公网的转发端口和本地端口就可以了。例如:我们需要将本地 3306 端口转发到公网中,使用下面命令即可。

# 可以自行设置公网端口,这里设置为
$ ssh -R :localhost: serveo.net # 如果公网端口设置为 ,就会采用一个随机端口进行转发
$ ssh -R :localhost: serveo.net

2、将本地 SSH 重定向到公网

在很多场景下,我们需要远程访问到本地计算机的 SSH 服务。要实现这样的需求也很简单,只需要使用下面的命令。

# 名称为自定义的,这里设置为 myhost
$ ssh -R myhost::localhost: serveo.net
Hi there
Forwarding SSH traffic from alias "myhost"
Press g to start a GUI session and ctrl-c to quit.
...

连接成功后,接下来你就可以从公网上对这个内网计算机的 SSH 进行访问了。

$ ssh -J serveo.net myuser@myhost
Hi there
myuser@myhost's password:
Last login: Mon Dec :: from 127.0.0.1
...

-J 选项是在 OpenSSH 7.3 版本才引入的,如果你使用的 SSH 客户端版本较旧,则可以使用 ProxyCommand 选项来替代。

$ ssh -o ProxyCommand="ssh -W myhost:22 serveo.net" user@myhost

一些其它技巧

1、保持 SSH 连接不超时

众所周知,SSH 连接一旦超时就会自动断开,这样就很容易造成服务中断。这里我们只需给 SSH 连接增加一个保活参数 -o ServerAliveInterval=60 就可以了。

# 每隔  秒做一次连接保活
$ ssh -o ServerAliveInterval= -R :localhost: serveo.net

2、对 SSH 连接进行守护

上面的方法虽然可以解决超时的问题,但进程始终是在前台运行的。为了彻底解决这个问题,官方推荐使用 AutoSSH 来进行进程守护。

AutoSSH 是一个用来对 SSH 连接进行监控的程序,可在遇到程序问题或者是网络问题时自动进行重连,以达到长期保持 SSH 稳定连接的目的 。

将 AutoSSH 加入到系统服务:

这里以加入到 Systemd 系统服务为例,此方法适用于 CentOS 7Debian 8Ubuntu 16 及以上系统版本。首先,我们创建一个 AutoSSH 的 Systemd 服务。

cat > /etc/systemd/system/serveo.service <<EOF
[Unit]
Description=autossh
After=network.target [Service]
Type=simple
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R wjoyxt::localhost: serveo.net
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always [Install]
WantedBy=multi-user.target
EOF

AutoSSH 的 -M 参数主要用于指定一个监听端口来监视 SSH 连接状态,这里指定为 0 的主要目的是禁用 AutoSSH 的监控端口。保活依然使用 SSH 自己的 ServerAliveInterval 和 ServerAliveCountMax 选项来完成。

其次,Systemd 系统服务创建完成后,我们启动这个 AutoSSH 的服务并设置为开机自启。

$ systemctl daemon-reload
$ systemctl start serveo
$ systemctl enable serveo

3、如果你无法通过 22 端口连接到 Serveo,官方还预留了 443 端口给你使用

$ ssh -p  -R :localhost: serveo.net

4、使用自定义的域名 / 子域名

默认情况下,我们都是使用的 Serveo 生成的二级域名进行连接的。如果你想使用自己的域名也是可以的,方法非常简单。只需要在你的域名所在 DNS 中添加一条 A 记录和一条 TXT 记录就可实现。

4.1 添加一条 A 记录

A | wjoyxt | 159.89.214.31

4.2 添加一条 TXT 记录

TXT | wjoyxt | authkeyfp=SHA256:pmc7ZRv7ymCmghUwHoJWEm5ToSTd33ryeDeps5RnfRY

authkeyfp 后面跟的那一串字符是 RSA 密钥指纹,你可以使用 ssh-keygen -l 命令进行查看。

DNS 解析记录增加好后,你就可以使用自定义域名进行连接了。

$ ssh -R wjoyxt.cnblogs.com::localhost: serveo.net

至此,Serveo 的基本用法就介绍完了。如果你对它有更多的兴趣,可以去官网进行探索。



利用autossh建立稳定隧道,前提双方互加公钥信任。

# yum install autossh -y

在被控内网主机上运行:

# autossh -M 65533 -f -NR 10000:localhost:22 abc@3322.org   [-p 51900]  -o "ServerAliveInterval=60" -o "ServerAliveCountMax=3"

autossh的参数与ssh的参数是一致的,但是不同的是,在隧道断开的时候,autossh会自动重新连接而ssh不会。另外不同的是我们需要指出的-M参数,这个参数指定一个端口,这个端口是外网的机器用来接收内网机器的信息,如果隧道不正常而返回信息给内网机器让他实现重新连接。

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

-M:You can disable the built-in AutoSSH monitoring port by giving it a value of 0,设为0的话,表示会禁用AutoSSH内置的监视端口(推荐)。

上面的autossh命令会另外开启一个子进程,端口号为 -M 后面的端口号+1 ,此处即 65534 。它会新建一个ssh子进程用来具体实现上面的功能

autossh 主进程 ---- 端口 65533

autossh 子进程 ---- 端口 65534

当用于连接的子进程挂掉后,主进程会重新启动一个子进程进行连接。

使用SSH客户端的ServerAliveInterval和ServerAliveCountMax选项。 ServerAliveInterval会在隧道无通信后的一段设置好的时间后发送一个请求给服务器要求服务器响应。如果服务器在 ServerAliveCountMax次请求后都没能响应,那么SSH客户端就自动断开连接并退出,将控制权交给你的监控程序。这两个选项的设置方法分别是在ssh时加入-o ServerAliveInterval=n和-o ServerAliveCountMax=m。其中n, m可以自行定义。

在进行调试autossh时,可以设置如下系统变量即可打印出详细信息:

export AUTOSSH_PIDFILE=/var/run/autossh.pid
export AUTOSSH_POLL=
export AUTOSSH_FIRST_POLL=
export AUTOSSH_GATETIME=
export AUTOSSH_DEBUG=

经过测试,在出现特殊情况导致重连失败时,可手动kill客户端连接R端口的进程,此处R端口为51901,之后即可恢复正常

例如:

$ ssh root@localhost -o ConnectTimeout= -p  "ls /yunwei"
ssh: connect to host localhost port : No route to host

# netstat -tulanp|grep 51901

tcp               127.0.0.1:51901         0.0.0.0:*               LISTEN      /sshd: root

# kill 22865


首先在被控内网主机上运行:

ssh -f -NR 10000:localhost:22 abc@3322.org  [-p 51900]

10000端口:在主控端服务器使用的隧道端口,可任意指定

22端口:被控内网主机的ssh连接端口

-p 2222:连接主控端的ssh连接端口,默认为22的话可省略

abc@3322.org:连接主控端使用的用户名和域名或IP地址

-f 后台执行

-N 仅用作port forwarding,不带执行远程命令

-R Port forwarding,如上,在22端口和10000端口间建立一条通道 (port:host:hostport)

-o option  可以在这里给出某些选项, 格式和配置文件中的格式一样. 它用来设置那些没有命令行开关的选项

然后在主控端运行:

ssh  def@localhost -p 51900

def:被控端服务器上已有用于ssh连接的用户名

进程服务化:

cat > /etc/systemd/system/autossh.service <<EOF
[Unit]
Description=autossh
After=network.target [Service]
#User=wjoyxt
Type=simple
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M -NR :localhost: root@39.101.101.166 -p -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3"
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always [Install]
WantedBy=multi-user.target
#WantedBy=graphical.target
EOF

解决ssh的"Write failed: Broken pipe"问题

问题现象:

用 ssh 命令连接服务器之后,如果一段时间不操作,再次进入 Terminal 时会有一段时间没有响应,然后就出现错误提示:

Write failed: Broken pipe

只能重新用 ssh 命令进行连接。

解决方法:

方法一:如果您有多台服务器,不想在每台服务器上设置,只需在客户端的 ~/.ssh/ 文件夹中添加 config 文件,并添加下面的配置:

ServerAliveInterval 60

方法二:如果您有多个人管理服务器,不想在每个客户端进行设置,只需在服务器的 /etc/ssh/sshd_config 中添加如下的配置:

ClientAliveInterval 60               

方法三:如果您只想让当前的 ssh 保持连接,可以使用以下的命令:

$ ssh -o ServerAliveInterval=60 user@sshserver

ssh-copy-id使用非默认22端口时:ssh-copy-id  "-p 5180  wjoyxt@abc.3322.org"   (必须要有引号)
cat >> /etc/ssh/sshd_config  << EOF
TCPKeepAlive yes              指定系统是否向客户端发送 TCP keepalive 消息。这种消息可以检测到死连接、连接不当关闭、客户端崩溃等异常,保证不会有僵尸程序的发生。
ClientAliveInterval 60        server端每60s就会向client端发送一个keep-alive包, 来保持连接
ClientAliveCountMax 10     指定发送keep-alive包(超时连接)的最大次数,超过该次数后会自动断开连接。
EOF

ssh反向连接内网主机的相关教程结束。

《ssh反向连接内网主机.doc》

下载本文的Word格式文档,以方便收藏与打印。