ssh的转发使用[转] 内网机通过公网机,其他机器可访问内网机

参考连接:https://wangdoc.com/ssh/port-forwarding

简介

SSH 除了登录服务器,还有一大用途,就是作为加密通信的中介,充当两台服务器之间的通信加密跳板,使得原本不加密的通信变成加密通信。这个功能称为端口转发(port forwarding),又称 SSH 隧道(tunnel)。

端口转发有两个主要作用:

(1)将不加密的数据放在 SSH 安全连接里面传输,使得原本不安全的网络服务增加了安全性,比如通过端口转发访问 Telnet、FTP 等明文服务,数据传输就都会加密。

(2)作为数据通信的加密跳板,绕过网络防火墙。

端口转发有三种使用方法:动态转发,本地转发,远程转发。下面逐一介绍。

动态转发

动态转发指的是,本机与 SSH 服务器之间创建了一个加密连接,然后本机内部针对某个端口的通信,都通过这个加密连接转发。它的一个使用场景就是,访问所有外部网站,都通过 SSH 转发。

动态转发需要把本地端口绑定到 SSH 服务器。至于 SSH 服务器要去访问哪一个网站,完全是动态的,取决于原始通信,所以叫做动态转发。

$ ssh -D local-port tunnel-host -N

上面命令中,-D表示动态转发,local-port是本地端口,tunnel-host是 SSH 服务器,-N表示这个 SSH 连接只进行端口转发,不登录远程 Shell,不能执行远程命令,只能充当隧道。

举例来说,如果本地端口是2121,那么动态转发的命令就是下面这样。

$ ssh -D 2121 tunnel-host -N

注意,这种转发采用了 SOCKS5 协议。访问外部网站时,需要把 HTTP 请求转成 SOCKS5 协议,才能把本地端口的请求转发出去。

下面是 SSH 隧道建立后的一个使用实例。

$ curl -x socks5://localhost:2121 http://www.example.com

上面命令中,curl 的-x参数指定代理服务器,即通过 SOCKS5 协议的本地2121端口,访问http://www.example.com

如果经常使用动态转发,可以将设置写入 SSH 客户端的用户个人配置文件(~/.ssh/config)。

DynamicForward tunnel-host:local-port

本地转发

本地转发(local forwarding)指的是,创建一个本地端口,将发往该端口的所有通信都通过 SSH 服务器,转发到指定的远程服务器的端口。这种情况下,SSH 服务器只是一个作为跳板的中介,用于连接本地计算机无法直接连接的远程服务器。本地转发是在本地计算机建立的转发规则。

它的语法如下,其中会指定本地端口(local-port)、SSH 服务器(tunnel-host)、远程服务器(target-host)和远程端口(target-port)。

$ ssh -L -N -f local-port:target-host:target-port tunnel-host

上面命令中,有三个配置参数。

  • -L:转发本地端口。
  • -N:不发送任何命令,只用来建立连接。没有这个参数,会在 SSH 服务器打开一个 Shell。
  • -f:将 SSH 连接放到后台。没有这个参数,暂时不用 SSH 连接时,终端会失去响应。

举例来说,现在有一台 SSH 服务器tunnel-host,我们想要通过这台机器,在本地2121端口与目标网站www.example.com的80端口之间建立 SSH 隧道,就可以写成下面这样。

$ ssh -L 2121:www.example.com:80 tunnel-host -N

然后,访问本机的2121端口,就是访问www.example.com的80端口。

$ curl http://localhost:2121

注意,本地端口转发采用 HTTP 协议,不用转成 SOCKS5 协议。

另一个例子是加密访问邮件获取协议 POP3。

$ ssh -L 1100:mail.example.com:110 mail.example.com

上面命令将本机的1100端口,绑定邮件服务器mail.example.com的110端口(POP3 协议的默认端口)。端口转发建立以后,POP3 邮件客户端只需要访问本机的1100端口,请求就会通过 SSH 服务器(这里是mail.example.com),自动转发到mail.example.com的110端口。

上面这种情况有一个前提条件,就是mail.example.com必须运行 SSH 服务器。否则,就必须通过另一台 SSH 服务器中介,执行的命令要改成下面这样。

$ ssh -L 1100:mail.example.com:110 other.example.com

上面命令中,本机的1100端口还是绑定mail.example.com的110端口,但是由于mail.example.com没有运行 SSH 服务器,所以必须通过other.example.com中介。本机的 POP3 请求通过1100端口,先发给other.example.com的22端口(sshd 默认端口),再由后者转给mail.example.com,得到数据以后再原路返回。

注意,采用上面的中介方式,只有本机到other.example.com的这一段是加密的,other.example.commail.example.com的这一段并不加密。

这个命令最好加上-N参数,表示不在 SSH 跳板机执行远程命令,让 SSH 只充当隧道。另外还有一个-f参数表示 SSH 连接在后台运行。

如果经常使用本地转发,可以将设置写入 SSH 客户端的用户个人配置文件(~/.ssh/config)。

Host test.example.com
LocalForward client-IP:client-port server-IP:server-port

远程转发

远程转发指的是在远程 SSH 服务器建立的转发规则。

它跟本地转发正好反过来。建立本地计算机到远程 SSH 服务器的隧道以后,本地转发是通过本地计算机访问远程 SSH 服务器,而远程转发则是通过远程 SSH 服务器访问本地计算机。它的命令格式如下。

$ ssh -R remote-port:target-host:target-port -N remotehost

上面命令中,-R参数表示远程端口转发,remote-port是远程 SSH 服务器的端口,target-hosttarget-port是目标服务器及其端口,remotehost是远程 SSH 服务器。

远程转发主要针对内网的情况。下面举两个例子。

第一个例子是内网某台服务器localhost在 80 端口开了一个服务,可以通过远程转发将这个 80 端口,映射到具有公网 IP 地址的my.public.server服务器的 8080 端口,使得访问my.public.server:8080这个地址,就可以访问到那台内网服务器的 80 端口。

$ ssh -R 8080:localhost:80 -N my.public.server

上面命令是在内网localhost服务器上执行,建立从localhostmy.public.server的 SSH 隧道。运行以后,用户访问my.public.server:8080,就会自动映射到localhost:80

第二个例子是本地计算机local在外网,SSH 跳板机和目标服务器my.private.server都在内网,必须通过 SSH 跳板机才能访问目标服务器。但是,本地计算机local无法访问内网之中的 SSH 跳板机,而 SSH 跳板机可以访问本机计算机。

由于本机无法访问内网 SSH 跳板机,就无法从外网发起 SSH 隧道,建立端口转发。必须反过来,从 SSH 跳板机发起隧道,建立端口转发,这时就形成了远程端口转发。跳板机执行下面的命令,绑定本地计算机local2121端口,去访问my.private.server:80

$ ssh -R 2121:my.private.server:80 -N local

上面命令是在 SSH 跳板机上执行的,建立跳板机到local的隧道,并且这条隧道的出口映射到my.private.server:80

显然,远程转发要求本地计算机local也安装了 SSH 服务器,这样才能接受 SSH 跳板机的远程登录。

执行上面的命令以后,跳板机到local的隧道已经建立了。然后,就可以从本地计算机访问目标服务器了,即在本机执行下面的命令。

$ curl http://localhost:2121

本机执行上面的命令以后,就会输出服务器my.private.server的 80 端口返回的内容。

如果经常执行远程端口转发,可以将设置写入 SSH 客户端的用户个人配置文件(~/.ssh/config)。

Host remote-forward
  HostName test.example.com
  RemoteForward remote-port target-host:target-port

完成上面的设置后,执行下面的命令就会建立远程转发。

$ ssh -N remote-forward

# 等同于
$ ssh -R remote-port:target-host:target-port -N test.example.com

实例

下面看两个端口转发的实例。

简易 VPN

VPN 用来在外网与内网之间建立一条加密通道。内网的服务器不能从外网直接访问,必须通过一个跳板机,如果本机可以访问跳板机,就可以使用 SSH 本地转发,简单实现一个 VPN。

$ ssh -L 2080:corp-server:80 -L 2443:corp-server:443 tunnel-host -N

上面命令通过 SSH 跳板机,将本机的2080端口绑定内网服务器的80端口,本机的2443端口绑定内网服务器的443端口。

两级跳板

端口转发可以有多级,比如新建两个 SSH 隧道,第一个隧道转发给第二个隧道,第二个隧道才能访问目标服务器。

首先,在本机新建第一级隧道。

$ ssh -L 7999:localhost:2999 tunnel1-host

上面命令在本地7999端口与tunnel1-host之间建立一条隧道,隧道的出口是tunnel1-hostlocalhost:2999,也就是tunnel1-host收到本机的请求以后,转发给自己的2999端口。

然后,在第一台跳板机(tunnel1-host)执行下面的命令,新建第二级隧道。

$ ssh -L 2999:target-host:7999 tunnel2-host -N

上面命令将第一台跳板机tunnel1-host2999端口,通过第二台跳板机tunnel2-host,连接到目标服务器target-host7999端口。

最终效果就是,访问本机的7999端口,就会转发到target-host7999端口。

参考链接

 

 

 

 

 

上面是我复制的内容,我主要讲一些我需要用到的内容。
我单位一台内网的机器,我需要再外面通过ssh连接到该机器,所有我使用的是ssh -R的端口转发功能,也就是内网机器连接到公网的服务器,
其他机器通过连接到这个公网的服务器指定端口,就好比直接连接到内网机器的效果
ssh -N -R 2222:localhost:22 zl_lenovo
我使用的是这个命令,2222是公网机器打开的端口,22是本地转发的端口,最后的是公网的机器
使用的原理,就是连接成功后,公网机器会监听2222的端口,然后将接受到的数据转发到内网机器的22端口
这里有一个需要提醒的地方,默认公网的机器监控的是localhost:2222端口

要让跳板机上的某个端口(如2222)能够接受来自任何地址的连接请求,你需要在创建反向隧道时采取额外步骤,使端口在所有接口上监听,或者修改跳板机的SSH配置:

  1. 修改SSH配置(跳板机上):

    • 编辑 /etc/ssh/sshd_config 文件。
    • 找到或添加 GatewayPorts 配置项,设置为 yesclientspecified
    • 重启SSH服务以应用更改。

通过修改sshd的配置文件,可以将端口改成公网监听,这样就实现了,从外网可以访问到内网机器的原理

记得最后调整防火墙的配置,这里又被埋了一个小时

这两条iptables命令的主要区别在于它们向规则链中添加规则的位置:

  1. -A(Append):

    • sudo iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
    • 这条命令使用-A选项将规则附加到INPUT链的末尾。这意味着,如果有其他先前的规则可能拒绝或以其他方式处理到达端口2222的流量,那么这条新添加的允许规则可能永远不会被评估或执行,因为iptables会按顺序处理规则,直到找到第一个匹配的规则。
  2. -I(Insert):

    • sudo iptables -I INPUT -p tcp --dport 2222 -j ACCEPT
    • 使用-I选项会将规则插入到INPUT链的开始位置。这意味着,这条规则会在任何其他规则之前被评估,从而确保针对端口2222的流量被允许,即使后面有规则指定拒绝或其他处理也不会影响到这条规则的效果。

为什么第二个命令有效

如果你发现使用第二个命令(-I选项)之后能够成功连接,而第一个命令(-A选项)不行,那很可能是因为INPUT链中存在其他规则,在这条规则被添加到末尾时,这些规则先于它被处理,可能已经匹配并处理了到达端口2222的流量(例如通过拒绝或丢弃)。当你使用-I选项将规则插入到链的最开始时,它确保了对端口2222的访问首先匹配这条允许规则,从而允许流量通过。

 

这里有需要对autossh的使用做一些补充,以及公网机的sshd的设置进行补充.

ssh -R 2222:localhost:22 -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes user@remotehost

 

  1. -o ExitOnForwardFailure=yes 确保如果端口转发不能成功设置(比如端口已被占用),SSH客户端会立即退出,而不是无视转发失败保持连接。这有助于避免在预期的端口转发没有建立的情况下留下一个无用的SSH会话。

  2. -o ServerAliveInterval=30 配置SSH客户端每30秒向服务器发送一个空包,以保持连接活跃并检查连接是否仍然有效。

  3. -o ServerAliveCountMax=3 设置了在没有收到服务器响应的情况下客户端尝试发送这种保活包的最大次数。如果达到这个次数仍然没有响应,客户端会断开连接。

将这些选项结合使用,可以增强SSH隧道的稳定性和鲁棒性,尤其是在动态或不稳定的网络环境中。如果隧道的建立失败,或者连接在一段时间后变得不稳定,这些选项能够确保SSH客户端及时响应这些情况,避免潜在的问题。

 

这三个参数一加,能确保autossh 执行的时候,能够及时的重启ssh

 

在跳板机(SSH服务器端)上,你也可以通过设置ClientAliveIntervalClientAliveCountMax来确保在客户端不响应时关闭连接。这些选项在/etc/ssh/sshd_config文件中设置。

ClientAliveInterval 30
ClientAliveCountMax 3

这表示服务器每30秒检查一次客户端是否活跃,如果连续3次检查失败,则服务器端SSH将断开连接。

这两个需要在公网服务器上面设置,因为通过这个设置能够让主机上及时关闭异常的ssh连接,也就是内网机连接到跳板机让跳板机开启的连接,
当内网机关闭或者切换ssh连接的时候,及时关闭这个连接。

 

posted @ 2024-03-20 16:58  就是想学习  阅读(322)  评论(0编辑  收藏  举报