通过SSH实现 TCP / IP隧道(端口转发)

通过 SSH 实现 TCP / IP 隧道(端口转发)

参考文档:

https://blog.csdn.net/jiangbenchu/article/details/84438959

https://help.ubuntu.com/community/SSH/OpenSSH/PortForwarding

https://www.linuxprobe.com/ssh-port-forward.html

https://blog.csdn.net/weixin_43934607/article/details/108640502

http://arondight.me/2016/02/17/%E4%BD%BF%E7%94%A8SSH%E5%8F%8D%E5%90%91%E9%9A%A7%E9%81%93%E8%BF%9B%E8%A1%8C%E5%86%85%E7%BD%91%E7%A9%BF%E9%80%8F/

https://superuser.com/questions/235395/automatic-ssh-tunneling-from-windows

https://mobaxterm.mobatek.net/download-home-edition.html

https://code.google.com/archive/p/ssh-tunnel-manager/downloads

https://www.cnblogs.com/freedom-try/p/12574266.html

前言

由于业务需要公司采购了 科大讯飞的单节点本地服务,前期本地调试开发的时候没有遇到什么问题,但是项目上线之后就发现部署在 **政务外网(类似于公网)**的应用没有办法调用该服务。

最开始使用的是 tunnel(内网穿透) 服务(需要一个公网ip),但是由于公司服务器公网服务器时常有问题,被逼之下只能尝试使用其它方案。

经过了解最终考虑使用 SSH隧道 来做端口转发,从而来解决这个问题。

1、ssh隧道的端口转发分为三种:

为了方便介绍我们简单介绍一下情况:本地IP地址(192.168.1.100),公网IP地址(172.20.9.69)

  • 本地端口转发:内网IP地址192.168.1.100 通过ssh连接到公网地址 172.20.9.69,当访问内网服务器的特定端口(例如:8080)则会将当前请求通过ssh转发到公网服务器的特定端口(例如:9876),从一定程度上可以理解为在本地做了一个正向代理
  • 远程端口转发:内网IP地址192.168.1.100 通过ssh连接到公网地址 172.20.9.69,当在公网服务器中访问特定的端口(例如:8083)会将当前请求转发到内网服务器的特定端口(例如:9876)
  • **动态端口转发也成为(SOCKS 代理):**动态端口转发将您的 SSH 客户端变成SOCKS 代理服务器,通常情况下被用作跳板机。例如你本地网络访问不了:https://www.redhat.com/, 但是你公网服务器可以访问该网站,然后你就可以通过socks 代理来实现本地访问该网站。

2、对应的图片如下:

本地端口转发

本地端口转发

远程端口转发

远程端口转发

动态端口转发

动态端口转发

3、使用到的ssh命令参数:

  • "-p":指定远程主机的端口
  • "-C": 允许压缩数据,这在主要代理基于文本的信息(如网页浏览)时加快隧道速度,但在代理二进制信息(如下载文件)时会减慢速度。
  • "-N": 不执行远程指令
  • "-L": 使用本地端口转发,将本地机(客户机)的某个端口转发到远端指定机器的指定端口
  • “-R”: 使用转成端口转发,将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口
  • "-f": 后台执行ssh命令
  • "-D": 指定动态端口转发(SOCKS 代理),1080是标准的 SOCKS 端口。尽管您可以使用任何端口号,但某些程序只有在您使用1080 时才能运行.

4、准备工作

4.1、准备免密登录的操作

第一步:生成密钥:(在需要免密登录的服务器上执行)

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/milory/.ssh/id_rsa): 
Created directory '/home/milory/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/milory/.ssh/id_rsa
Your public key has been saved in /home/milory/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:99BZcKuLH3idlh/7LhRHuVzo7ZsihL/OTLT/qZgJUKg milory@milory-pc
The key's randomart image is:
+---[RSA 3072]----+
|            . ...|
|        .    o.oo|
|       . .   .+oo|
|      . .  . +ooo|
|     E .S +.+  + |
|        .o.*.o.o.|
|         .=o=.=.o|
|          ===+.++|
|          .O+o+*=|
+----[SHA256]-----+

第二步:查看生成的密钥

$ ll ~/.ssh/
total 16
drwx------ 2 milory milory 4096 Nov 24 12:06 ./
drwxr-xr-x 4 milory milory 4096 Nov 24 12:06 ../
-rw------- 1 milory milory 2602 Nov 24 12:06 id_rsa
-rw-r--r-- 1 milory milory  570 Nov 24 12:06 id_rsa.pub

第三步:在公网服务器中创建 authorized_keys文件

$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

第四步:将内网生成的公钥文件内容复制到公网的authorized_keys文件中

# .pub值写入远程机器的 ~/.ssh/authorized_key中
$ ssh-copy-id -i ~/.ssh/id_rsa.pub gdgxkj@192.168.1.140
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/milory/.ssh/id_rsa.pub"
The authenticity of host '192.168.1.140 (192.168.1.140)' can't be established.
ECDSA key fingerprint is SHA256:U5FFtbagp3Jeie1A2CZC/ZOvngiBmCQQxm7SfJrCabo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
gdgxkj@192.168.1.140's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'gdgxkj@192.168.1.140'"
and check to make sure that only the key(s) you wanted were added.
4.2、ssh服务的配置

由于我们的正式环境的22端口不能直接访问,所以就需要修改ssh服务的默认端口(或者新添加一个监听端口),所以需要ssh服务的配置,

而 ssh服务的配置文件为:/etc/ssh/sshd_config,原始的内容如下:

$ cat /etc/ssh/sshd_config
# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/bin:/usr/bin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

# If you want to change the port on a SELinux system, you have to tell
# SELinux about this change.
# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER
#
#Port 22
protocol 2
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::

HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
SyslogFacility AUTHPRIV
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin yes
#StrictModes yes
MaxAuthTries 5
#MaxSessions 10

#PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile      .ssh/authorized_keys

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
PasswordAuthentication yes

# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
ChallengeResponseAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
#KerberosUseKuserok yes

# GSSAPI options
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
#GSSAPIEnablek5users no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several
# problems.
UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#UsePrivilegeSeparation sandbox
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#ShowPatchLevel no
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# Accept locale-related environment variables
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS

# override default of no subsystems
Subsystem       sftp    /usr/libexec/openssh/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server

修改之后的内容如下:

# 先备份原始的配置文件
$ cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# 将相关的配置内容添加到/etc/ssh/sshd_config文件
$ cat >> /etc/ssh/sshd_config <<EOF

# 内网穿透的配置如下:===============>
# 是否允许远程主机连接本地的转发端口
GatewayPorts yes
# 是否保持连接
TcpKeepAlive yes
# 心跳发送间隔
ClientAliveInterval 30
# 心跳发送最大失败次数
ClientAliveCountMax 5
EOF

由于安全需要则在ssh的监听端口中添加一个 5222端口,如果可以访问默认的22端口则跳过当前操作:

$ sed -i 's/#Port 22/Port 22\nPort 5222/g' /etc/ssh/sshd_config

以上命令的意思是将 /etc/ssh/sshd_config 文件中的字符串 “#Port 22” 替换为:“Port 22回车Port 5222”

最后重启需要重启ssh服务:

$ systemctl restart sshd.service

一、本地端口转发

将本地机器(内网)的某个端口转发到远端指定机器(公网)的指定端口。

服务器的列表如下:

描述ip地址操作系统ssh服务端口配置
公网192.168.1.140Centos-7.65222
内网192.168.198.130Ubuntu 20.04.3 LTS

在内网的192.168.198.130服务器上执行如下命令:

格式如下:-L [绑定本地的IP:]本地需要转发的端口:远程的IP:需要转发到的远程端口

缺省情况下绑定的是本地的:127.0.0.1

# 本地监听1234端口,将1234端口的流量都转发到远程的80端口
$ ssh -p 5222 -fCNL 1234:192.168.1.140:80 gdgxkj@192.168.1.140

# 查看端口绑定情况,可以看到本地IP缺省的情况下绑定的是:127.0.0.1
$ netstat -ntlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:1234          0.0.0.0:*               LISTEN      4677/ssh            
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp6       0      0 ::1:1234                :::*                    LISTEN      4677/ssh            
tcp6       0      0 :::22                   :::*                    LISTEN      -                   

# 访问本地的1234端口
$ curl http://127.0.0.1:1234
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit">..........

绑定本地的所有ip地址:

格式如下:*-L :本地需要转发的端口:远程的IP:需要转发到的远程端口

# 本地监听1234端口,将1234端口的流量都转发到远程的80端口
$ ssh -p 5222 -fCNL *:1234:192.168.1.140:80 gdgxkj@192.168.1.140

# 再次查看,可以看到已经绑定本地所有的ip地址了
$ netstat -ntlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:1234            0.0.0.0:*               LISTEN      5247/ssh            
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -           
tcp        0      0 0.0.0.0:5222            0.0.0.0:*               LISTEN      -  
tcp6       0      0 :::1234                 :::*                    LISTEN      5247/ssh            
tcp6       0      0 :::22                   :::*                    LISTEN      -                   

# 通过本地的ip地址来访问
$ curl http://192.168.198.130:1234

二、远程端口转发

将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口

服务器的列表如下:

描述ip地址操作系统ssh服务端口配置
公网192.168.1.140Centos-7.65222
内网192.168.198.130Ubuntu 20.04.3 LTS

在内网的192.168.198.130服务器上执行如下命令:

格式如下:-R [绑定远程的IP:]远程需要转发的端口:本地的IP:需要转发到的本地端口

缺省情况下绑定的是本地的:127.0.0.1

# 在内网执行当前命令,当前命令的意思是:监听远程的8888端口,并将8888的端口流量转发到本地的80端口
$ ssh -p 5222 -fCNR  *:8888:127.0.0.1:80  gdgxkj@192.168.1.140

# 在远程服务器上执行如下命令,查看远程的服务器监听的端口
$ netstat -ntlp | grep 8888
tcp        0      0 0.0.0.0:8888            0.0.0.0:*               LISTEN      46252/sshd: gdgxkj  
tcp6       0      0 :::8888                 :::*                    LISTEN      46252/sshd: gdgxkj

# 在远程服务器访问8888端口
$ curl http://127.0.0.1:8888
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

三、远程端口转发

‎动态端口转发允许您在本地(ssh 客户端)计算机上创建一个套接字,该套接字充当 SOCKS 代理服务器。当客户端连接到此端口时,连接将转发到远程(ssh 服务器)计算机,然后将其转发到目标计算机上的动态端口。‎

‎这样,使用 SOCKS 代理的所有应用程序都将连接到 SSH 服务器,并且服务器会将所有流量转发到其实际目标。‎

‎在Linux,macOS和其他Unix系统中创建动态端口转发(SOCKS)将选项传递给客户端:,执行的格式如下:

ssh -D [LOCAL_IP:]LOCAL_PORT [USER@]SSH_SERVER

服务器的列表如下:

描述ip地址操作系统ssh服务端口配置
公网192.168.1.140Centos-7.65222
内网192.168.198.130Ubuntu 20.04.3 LTS

第一步:建立动态端口转发通道

# 指定动态端口转发的端口为:1080,并指定后台运行
$ ssh -D 1080 -fCN -p 22 gdgxkj@192.168.1.140

第二步:在本地查看监听的端口

# 可以看到本地已经监听了1080端口了
$ netstat -ntlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:1080          0.0.0.0:*               LISTEN      24255/ssh           
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:1080                :::*                    LISTEN      24255/ssh                

第三步:使用curl来测试

# 现在公网服务器上进行测试
$ curl http://127.0.0.1:19999
[{"name":"meeting-api","url":"/meeting-api/v2/api-docs"....................}]

# 然后在内网服务上执行测试,并不能访问通
$ curl http://127.0.0.1:19999/
curl: (7) Failed to connect to 127.0.0.1 port 19999: Connection refused

# 然后在内网服务上使用SOCKS代理再执行测试,发现已经可以访问了
# crul 版本 >= 7.21.7 时使用命令:
$ curl -x socks5h://localhost:1080 http://127.0.0.1:19999/
[{"name":"meeting-api","url":"/meeting-api/v2/api-docs"....................}]

# crul 版本 >= 7.18.0 时使用命令:
$ curl --socks5-hostname localhost:1080 http://127.0.0.1:19999/

四、autossh的使用

4.1、引子

虽然说上面的方式可以实现功能,但是ssh链接会因为超时而关闭,如果关闭了那从外网连通内网的通道就无法维持了,为此我们需要另外的方法来提供稳定的ssh反向代理隧道。

为此我们就引出了 autossh 命令。

4.2、安装autossh

centos7上没有默认安装autossh的,所以使用以下命令安装

$ sudo yum install autossh

Ubuntu中默认也是没有安装autossh的,所以使用以下命令安装

$ sudo apt install autossh

4.3、autossh参数说明

格式: autossh [-V] [-M monitor_port[:echo_port]] [-f] [SSH_OPTIONS]

  • "-M": 指定监控端口。 覆盖环境变量 AUTOSSH_PORT。 0 关闭监控回路。 或者,可以指定远程机器上回显服务的端口。 (通常是端口 7。)
  • "-f": 在后台运行(autossh 处理此问题,并且不会将其传递给 ssh。)
  • "-V": 打印 autossh 版本并退出。

环境变量选项如下:

  • "AUTOSSH_GATETIME":在我们确定 ssh 会话真正建立之前必须建立多长时间(以秒为单位)。 默认为 30 秒; 使用 -f 标志将此设置为 0。
  • "AUTOSSH_LOGFILE": 日志文件写入的文件(默认使用系统日志工具- syslog facility)
  • "AUTOSSH_LOGLEVEL":日志详细程度
  • "AUTOSSH_MAXLIFETIME":设置最长存活时间(秒)
  • “AUTOSSH_MAXSTART”:最大重启次数(默认为无限制)
  • “AUTOSSH_MESSAGE”:添加到回显字符串的消息(最大 64 字节)
  • “AUTOSSH_PATH”:ssh命令 的路径(如果不是默认值)
  • “AUTOSSH_PIDFILE”:将pid写入此文件
  • “AUTOSSH_POLL”:检查连接的频率(秒)
  • “AUTOSSH_FIRST_POLL”:第一次连接检查前的时间(秒)
  • “AUTOSSH_PORT”:用于监视器连接的端口
  • “AUTOSSH_DEBUG”:将日志记录到最大详细程度并记录到 stderr

4.4、autossh建立稳定隧道-监听端口方式

autossh的参数与ssh的参数是一致的,但是不同的是,在隧道断开的时候,autossh会自动重新连接而ssh不会。

另外不同的是我们需要指出的 -M 参数,这个参数指定一个端口,这个端口是外网的B机器用来接收内网A机器的信息,如果隧道不正常而返回给A机器让他实现重新连接。

# 在本地执行如下命令,建立隧道
$  autossh -M 7281 -fCNR *:7280:127.0.0.1:80 gdgxkj@192.168.1.140


# 查看本地端口监听情况
$ netstat -ntlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:7281          0.0.0.0:*               LISTEN      27489/ssh           
tcp        0      0 127.0.0.1:7282          0.0.0.0:*               LISTEN      27488/autossh       
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:7281                :::*                    LISTEN      27489/ssh           
tcp6       0      0 :::22                   :::*                    LISTEN      -                   

# 查看公网服务器的端口占用情况,可以看到在远程建立一个 7281的监听端口
$ netstat -ntlp | grep gdgxkj
tcp        0      0 0.0.0.0:7280            0.0.0.0:*               LISTEN      18356/sshd: gdgxkj  
tcp        0      0 0.0.0.0:7281            0.0.0.0:*               LISTEN      18356/sshd: gdgxkj  
tcp6       0      0 :::7280                 :::*                    LISTEN      18356/sshd: gdgxkj  
tcp6       0      0 :::7281                 :::*                    LISTEN      18356/sshd: gdgxkj

关于 -M参数的详情:

specifies the base monitoring port to use. Without the echo port, this port and the port immediately above it ( port + 1) should be something nothing else is using.

指定要使用基本的监控端口。如果没有显式指定端口,那么这个端口和它上面的端口(端口 + 1)应该确定没有其他程序使用使用。

autossh will send test data on the base monitoring port, and receive it back on the port above. For example, if you specify “-M 20000”, autossh will set up forwards so that it can send data on port 20000 and receive it back on 20001.

autossh 将在基本监控端口上发送测试数据,并在上面的端口上接收它。比如,如果你指定了“-M 20000”,autossh将会设置转发,以便与它可以在20000端口发送数据,在20001端口接收数据。

Alternatively, a port for a remote echo service may be specified. This should be port 7 if you wish to use the standard inetd echo service. When an echo port is specified, only the specified monitor port is used, and it carries the monitor message in both directions.

或许,可以指定远程echo服务的端口。如果你希望使用标准的 inetd echo服务,那么这应该是端口7。当echo 端口被指定了,只使用指定的监控端口,它会双向携带监控信息。

Many people disable the echo service, or even disable inetd, so check that this service is available on the remote machine. Some operating systems allow one to specify that the service only listen on the localhost (loopback interface), which would suffice for this use.

很多人禁用了 echo 服务,甚至禁用了 inetd,因此请检查该服务在远程机器上是否可用。某些操作系统允许指定服务仅侦听本地主机(环回接口),这足以满足此用途。

The echo service may also be something more complicated: perhaps a daemon that monitors a group of ssh tunnels.

echo 服务也可能是更复杂的东西:也许是监控一组 ssh tunnels 的守护进程。

Setting the monitor port to 0 turns the monitoring function off, and autossh will only restart ssh upon ssh’s exit. For example, if you are using a recent version of OpenSSH, you may wish to explore using the ServerAliveInterval and ServerAliveCountMax options to have the SSH client exit if it finds itself no longer connected to the server. In many ways this may be a better solution than the monitoring port.

将监控端口设置为 0 时则会关闭监控功能,并且 autossh 只会在 ssh 退出时重新启动 ssh。 例如,如果您使用的是最新版本的 OpenSSH,您可能希望探索使用 ServerAliveInterval 和 ServerAliveCountMax 选项在 SSH 客户端发现自己不再连接到服务器时退出。 在许多方面,这可能是比监控端口更好的解决方案。

4.5、autossh建立稳定隧道-发送心跳方式

介绍一下ssh命令的参数:

  • ServerAliveCountMax

设置可以在没有 ssh 从服务器接收任何消息的情况下发送的服务器活动消息的数量(也就是断开连接)。

如果达到此阈值而服务器活动消息正在发送,ssh 将断开与服务器的连接,终止会话。

需要注意的是,服务器活动消息的使用是与 TCPKeepAlive(如下)非常不同。 服务器活动消息通过加密通道发送,因此不会被欺骗。

TCP保活TCPKeepAlive 启用的选项是可欺骗的。 当客户端或服务器依赖于知道连接何时变为非活动状态时,服务器活动机制很有价值。

默认值为 3。例如,如果 ServerAliveInterval(见下文)设置为 15 并且 ServerAliveCountMax 保留为默认值,如果服务器无响应,ssh 将在大约 45 秒后断开连接。

  • ServerAliveInterval

以秒为单位设置超时间隔,如果没有从服务器接收到数据,ssh将通过加密通道发送消息以请求服务器的响应。 默认为 0,表示这些消息不会发送到服务器。

第一步:建立连接通道

# -M 0表示关闭端口监控功能
$ autossh -M 0 -f -CNR *:7280:127.0.0.1:80 gdgxkj@192.168.1.140 \
-o "ServerAliveInterval 60" \
-o "ServerAliveCountMax 3" \
-o BatchMode=yes \
-o StrictHostKeyChecking=no

第二步:在公网服务器上测试:

$ netstat -ntlp | grep gdgxkj
tcp        0      0 0.0.0.0:7280            0.0.0.0:*               LISTEN      13617/sshd: gdgxkj  
tcp6       0      0 :::7280                 :::*                    LISTEN      13617/sshd: gdgxkj


# 测试连接情况
$ curl http://127.0.0.1:7280
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

第三步:测试手动kill掉通道进程,测试是否可以重启

# 查看进程为13617
$ netstat -ntlp | grep gdgxkj
tcp        0      0 0.0.0.0:7280            0.0.0.0:*               LISTEN      13617/sshd: gdgxkj  
tcp6       0      0 :::7280                 :::*                    LISTEN      13617/sshd: gdgxkj

# kill掉当前进程
$ kill -9 13617

# 再次执行查看端口占用情况,发现确实被kill掉了,但是它又重启了
$ netstat -ntlp | grep gdgxkj
tcp        0      0 0.0.0.0:7280            0.0.0.0:*               LISTEN      4071/sshd: gdgxkj   
tcp6       0      0 :::7280                 :::*                    LISTEN      4071/sshd: gdgxkj

第四步:手动关闭内网服务器,查看三分钟后服务是否还在

# 在本地服务器上操作
$ date +%Y-%m-%d\ %H:%M:%S
2021-11-25 07:36:06

# 然后本地服务器
$ sudo poweroff

# 几分钟后查看公网服务器的进程是否还在(这里已经没有输出了)
$ netstat -ntlp | grep gdgxkj

4.6、配置autossh服务自动重启

以上指令已经可以完成所需的功能了,但是每次开机都得重新输一遍,很不方便,所以可以把指令封装成一个服务,然后设置为开机启动。

ubuntu中,可以在lib/systemd/system目录下新建一个autossh.service的文件,并输入以下内容:

[Unit]
Description=Auto SSH Tunnel
After=network-online.target
[Service]
User=autossh
Type=simple
ExecStart=/usr/bin/autossh -M 0 -f -CNR *:7280:127.0.0.1:80 gdgxkj@192.168.1.140
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
StartLimitIntervalSec=5
StartLimitBurst=12
Restart=always
[Install]
WantedBy=multi-user.target
WantedBy=graphical.target

配置好后,通过以下指令完成启动、查询和自启动。

  • 启动服务:sudo systemctl autossh start
  • 查看状态:sudo service autossh status
  • 开机启动:sudo systemctl enable autossh.service

五、windows下的ssh隧道

5.1、方案一:autossh(不推荐)

也可以使用windows下的autossh进行操作,但是由于autossh默认路径下去寻找 ssh.exe 文件,所以需要指定 AUTOSSH_PATH 环境变量。

详情的参考地址为:https://www.cnblogs.com/h46incon/archive/2016/03/29/5331433.html,但个人感觉有坑,仅供参考。

autossh.exe的下载地址为:https://files.cnblogs.com/files/h46incon/autossh-cygwin.rar

5.2、方案二:使用第三方软件(推荐)

1、Mobaxterm(推荐使用)

官网地址:http://mobaxterm.mobatek.net/

说明:分为开源版本和商业版本,如果需要的转发通道不是很多(1-2个的话),可以直接使用开源版本;除此之外还支持软件自启启动通道,并提供了一个shell链接工具(简单体验了一下),感觉功能还是挺强大的,图形化界面操作起来很直观。

2、SSH Tunnel Manager(比较推荐)

官网地址:https://code.google.com/archive/p/ssh-tunnel-manager/

说明:完全免费开源,软件直接在google 上即可下载,当 Mobaxterm 的开源版本不满足需求的时候,可以使用该软件作为替代。并且该软件很小,也才只有7M左右。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值