天天看點

Linux系統之SSH端口轉發

Linux系統之SSH端口轉發

ssh端口轉發也叫ssh隧道,我們知道ssh用戶端與服務端之間的通訊會自動加密和解密,除此以外,ssh為其他tcp連接配接提供了一個安全的通道進行資料傳輸,并提供了一系列相應的加密和解密服務,這一過程被稱之為“隧道”。例如,Telnet,SMTP,LDAP這些tcp應用均能夠從中得益,避免了使用者名,密碼以及隐私資訊的銘文傳輸。與此同時,如果工作環境的防火牆限制了一些網絡端口的使用,隻要允許ssh連接配接,也能夠通過将TCP端口轉發,來使用ssh進行通訊。

  ssh端口轉發也叫ssh隧道,我們知道ssh用戶端與服務端之間的通訊會自動加密和解密,除此以外,ssh為其他tcp連接配接提供了一個安全的通道進行資料傳輸,并提供了一系列相應的加密和解密服務,這一過程被稱之為“隧道”。例如,Telnet,SMTP,LDAP這些tcp應用均能夠從中得益,避免了使用者名,密碼以及隐私資訊的銘文傳輸。與此同時,如果工作環境的防火牆限制了一些網絡端口的使用,隻要允許ssh連接配接,也能夠通過将TCP端口轉發,來使用ssh進行通訊。

  通過以上的闡述,不難發現SSH端口轉發給我們提供了兩大功能,一是加密ssh用戶端至ssh服務端之間的通訊資料;二是突破防火牆的限制完成之前無法建立的TCP連接配接;

  ssh端口轉發分三大類:

  1、本地端口轉發:把本地主機端口通過待登入主機端口轉發到遠端主機端口上去。本地端口轉發通過選項-L指定,其格式為

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>
      

  選項:

    -f:背景啟用

    -N:不打開遠端shell,處于等待狀态

    -g:啟用網關功能(這個選項需要把sshd_config配置檔案中的GatewayPorts 參數配置成yes )

實驗環境:

  通過上述得知,我們需要三台主機,一台是本地主機(A),一台是中間待登入主機(B),一台是遠端主機(C)。這三台主機分别是這樣的,本地主機可以通過ssh連接配接至中間主機,中間主機能夠通過ssh連接配接至遠端主機,但是本地主機不能直接通過ssh連接配接至遠端主機。

Linux系統之SSH端口轉發

解釋下上圖:A想通過網絡通路C,但是在A和C有防火牆,明确拒絕A的所有請求。A可以通過ssh和B連接配接,B可以和C連接配接。資料走向是這樣的,data---->A本地端口2048(假設是通過2048轉發)--->A連接配接SSH伺服器的某一端口---->B作為SSH服務端22号端口---->B作為Telnet用戶端連接配接C的某一端口---->C作為Telnet服務端端口23。

  明白了以上的闡述,下面來試驗吧。

  首先準備以上需要的主機3台,ip位址分别是:A是192.168.0.11,B是192.168.0.12,C是192.168.0.13

  在C上部署一個Telnet服務,并且在防火牆裡明确拒絕A的所有請求。

[root@host_C ~]# yum install telnet-server -y
Loaded plugins: fastestmirror, security
Setting up Install Process
Determining fastest mirrors
 * base: mirrors.aliyun.com
 * extras: mirrors.cn99.com
 * updates: mirrors.163.com
base                                                     | 3.7 kB     00:00     
epel                                                     | 5.3 kB     00:00     
epel/primary_db                                          | 6.1 MB     00:00     
extras                                                   | 3.4 kB     00:00     
extras/primary_db                                        |  29 kB     00:00     
updates                                                  | 3.4 kB     00:00     
updates/primary_db                                                     | 6.6 MB     00:00     
Resolving Dependencies
--> Running transaction check
---> Package telnet-server.x86_64 1:0.17-48.el6 will be installed
--> Processing Dependency: xinetd for package: 1:telnet-server-0.17-48.el6.x86_64
--> Running transaction check
---> Package xinetd.x86_64 2:2.3.14-40.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==============================================================================================
 Package                  Arch              Version                     Repository       Size
==============================================================================================
Installing:
 telnet-server            x86_64            1:0.17-48.el6               base             37 k
Installing for dependencies:
 xinetd                   x86_64            2:2.3.14-40.el6             base            122 k

Transaction Summary
==============================================================================================
Install       2 Package(s)

Total download size: 159 k
Installed size: 313 k
Downloading Packages:
(1/2): telnet-server-0.17-48.el6.x86_64.rpm                            |  37 kB     00:00     
(2/2): xinetd-2.3.14-40.el6.x86_64.rpm                                 | 122 kB     00:00     
----------------------------------------------------------------------------------------------
Total                                                         968 kB/s | 159 kB     00:00     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : 2:xinetd-2.3.14-40.el6.x86_64                                              1/2 
  Installing : 1:telnet-server-0.17-48.el6.x86_64                                         2/2 
  Verifying  : 1:telnet-server-0.17-48.el6.x86_64                                         1/2 
  Verifying  : 2:xinetd-2.3.14-40.el6.x86_64                                              2/2 

Installed:
  telnet-server.x86_64 1:0.17-48.el6                                                          

Dependency Installed:
  xinetd.x86_64 2:2.3.14-40.el6                                                               

Complete!
[root@host_C ~]# chkconfig telnet on
[root@host_C ~]# chkconfig xinetd on
[root@host_C ~]# service xinetd start
Starting xinetd:                                           [  OK  ]
[root@host_C ~]# chkconfig --list telnet
telnet          on
[root@host_C ~]# ss -ntl
State      Recv-Q Send-Q               Local Address:Port                 Peer Address:Port 
LISTEN     0      128                             :::22                             :::*     
LISTEN     0      128                              *:22                              *:*     
LISTEN     0      64                              :::23                             :::*     
[root@host_C ~]#       

說明:Telnet伺服器已經準備就緒,也看到了相應的端口是出于監聽的狀态,接下來添加防火牆規則,拒絕A的所有請求。

[root@host_C ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
[root@host_C ~]# iptables -A INPUT -s 192.168.0.11 -j REJECT
[root@host_C ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
REJECT     all  --  192.168.0.11         0.0.0.0/0           reject-with icmp-port-unreachable 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
[root@host_C ~]# 
      

  在主機A上建立與B連通的ssh隧道,并指定轉發特定端口2048(這個端口可以任意指定一個,不一定是這個)

[root@host_A ~]# telnet 192.168.0.13
Trying 192.168.0.13...
telnet: connect to address 192.168.0.13: Connection refused
[root@host_A ~]# ssh -L 2048:[email protected]:23 -Nf 192.168.0.12
The authenticity of host '192.168.0.12 (192.168.0.12)' can't be established.
RSA key fingerprint is 3d:c6:e6:3a:2d:76:34:ba:59:7a:1c:33:f2:0a:6b:95.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.0.12' (RSA) to the list of known hosts.
[email protected]'s password: 
[root@host_A ~]# ss -ntl
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN     0      128               127.0.0.1:2048                     *:*     
LISTEN     0      128                     ::1:2048                    :::*     
LISTEN     0      128                      :::22                      :::*     
LISTEN     0      128                       *:22                       *:*
[root@host_A ~]# ss -nt
State      Recv-Q Send-Q                                 Local Address:Port                                   Peer Address:Port 
ESTAB      0      0                                       192.168.0.11:13551                                  192.168.0.12:22    
ESTAB      0      52                                      192.168.0.11:22                                    192.168.0.232:8351        

  說明:主機A第一次連接配接主機B,是以會提示我們否相信對方公鑰的提示。可以看到在主機A上我們指定的端口2048,已經處于監聽狀态了,并且主機A和主機B已經建立連接配接,說明ssh隧道已經建立好了,接下來我們在來用主機A來連接配接本地2048端口。

[root@host_A ~]# telnet 127.0.0.1 2048
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
CentOS release 6.7 (Final)
Kernel 2.6.32-573.el6.x86_64 on an x86_64
in: root
Password: 
Login incorrect

login: test
Password: 
Last login: Mon Oct 28 03:01:05 from 192.168.0.12
[test@host_C ~]$ ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:b5:b3:f7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.13/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::20c:29ff:feb5:b3f7/64 scope link 
       valid_lft forever preferred_lft forever
[test@host_C ~]$ 
      

  說明:可以看到我們主機A可以正常連接配接主機C,這裡說一下Telnet預設不允許用root去連接配接,是以我們試着用root連接配接,它會拒絕我們,用普通使用者沒有問題。通過上面的本地端口轉發,我們發現一個問題,我們指定的端口監聽在127.0.0.1上,這樣一來,如果我們用其他主機來連接配接就是一個問題,怎麼樣才能讓它監聽在任何位址都可以連接配接的位址上呢?有辦法,我們隻需要在剛才的指令上加上-g選項,-g選項表示開啟網關功能。在指定-g選項前,我們一定要確定ssh伺服器上把GatewayPorts 參數配置成yes。

[root@host_b ~]# grep -i gatewayports /etc/ssh/sshd_config 
#GatewayPorts no
GatewayPorts yes
[root@host_b ~]# 
      

  說明:在本實驗host_b作為ssh伺服器的角色,是以我們要在B主機上更改其對應的參數。

[root@host_A ~]# ssh -L 2048:192.168.0.13:23 -fNg 192.168.0.12
[email protected]'s password: 
[root@host_A ~]# ss -ntl
State      Recv-Q Send-Q                                 Local Address:Port                                   Peer Address:Port 
LISTEN     0      128                                               :::2048                                             :::*     
LISTEN     0      128                                                *:2048                                              *:*     
LISTEN     0      128                                               :::22                                               :::*     
LISTEN     0      128                                                *:22                                                *:*     
[root@host_A ~]#
      

  說明:我們加了-g 選項後,我們所指定的端口監聽在×上面了,×表示任何位址,這樣我們就可以用網際網路位址去連接配接這個端口,進而達到連接配接C主機的目的。

[root@host_A ~]# telnet 192.168.0.11 2048
Trying 192.168.0.11...
Connected to 192.168.0.11.
Escape character is '^]'.
CentOS release 6.7 (Final)
Kernel 2.6.32-573.el6.x86_64 on an x86_64
in: test
Password: 
Last login: Mon Oct 28 03:06:55 from 192.168.0.12
[test@host_C ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:b5:b3:f7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.13/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::20c:29ff:feb5:b3f7/64 scope link 
       valid_lft forever preferred_lft forever
[test@host_C ~]$ 
      

  2、遠端端口轉發:把登入主機端口通過本地主機端口轉發到遠端主機。遠端端口轉發通過選項-R指定,其格式為

ssh -R <local port>:<remote host>:<remote port> <SSH hostname>
      

  說明:和上面對本地端口轉發不同的是,遠端端口轉發在本實驗中,host_b就充當着ssh用戶端的角色,host_a就充當着ssh服務端的角色,我們要在host_b 上執行ssh -R 2048:192.168.0.13:23 -fN 192.168.0.11

[root@host_b ~]# ssh -R 2048:192.168.0.13:23 -fN 192.168.0.11
[email protected]'s password: 
[root@host_b ~]# ss -nt
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
ESTAB      0      52     192.168.0.12:22                 192.168.0.232:7960               
ESTAB      0      0      192.168.0.12:33508              192.168.0.11:22                 
[root@host_b ~]# ss -ntl
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      80          :::3306                    :::*                  
LISTEN     0      32          :::21                      :::*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      100        ::1:25                      :::*                  
[root@host_b ~]# 
[root@host_A ~]# ss -ntl
State       Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
LISTEN      0      128               127.0.0.1:2048                     *:*     
LISTEN      0      128                     ::1:2048                    :::*     
LISTEN      0      128                      :::22                      :::*     
LISTEN      0      128                       *:22                       *:*     
[root@host_A ~]# ss -nt
State       Recv-Q Send-Q        Local Address:Port          Peer Address:Port 
ESTAB       0      0              192.168.0.11:22            192.168.0.12:33508 
ESTAB       0      52             192.168.0.11:22           192.168.0.232:8351  
[root@host_A ~]# 
      

  說明:我們在B上執行了相應的指令,在A上是可以看到對應的端口已經處于監聽狀态。在B上可以看到是一個任意端口連接配接着A上的22号端口。充分說明了A是ssh服務端,B是用戶端。

接下來我們在A端來連接配接剛才指定的端口

[root@host_A ~]# telnet 127.0.0.1 2048
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
CentOS release 6.7 (Final)
Kernel 2.6.32-573.el6.x86_64 on an x86_64
in: test
Password: 
Last login: Mon Oct 28 03:24:30 from 192.168.0.12
[test@host_C ~]$ ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:b5:b3:f7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.13/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::20c:29ff:feb5:b3f7/64 scope link 
       valid_lft forever preferred_lft forever
[test@host_C ~]$ 
      

  說明:可以看到我們是可以正常連接配接的。當然我這次是監聽在127.0.0.1上,如果要監聽在任意位址上,我們也可以在上面的指令加上-g選項,在A主機上確定其GatewayPorts這個參數是被開啟運作的。這裡就不在示範。

3、動态端口轉發:動态轉發不需要指定特定的目标主機和端口号,可以實作不加密的網絡連接配接,全部走SSH連接配接,進而提高安全性。動态轉發通過參數 -D 指定,其格式:

ssh -D <local port> <SSH Server>
      

  我們在C上搭建一個http服務。其網絡環境不變,A還是無法通路C,B可以通路C ,A通過B的代理來通路C

[root@host_C ~]# yum install -y httpd
Loaded plugins: fastestmirror, security
Setting up Install Process
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.cn99.com
 * updates: mirrors.163.com
Resolving Dependencies
--> Running transaction check
---> Package httpd.x86_64 0:2.2.15-69.el6.centos will be installed
--> Processing Dependency: httpd-tools = 2.2.15-69.el6.centos for package: httpd-2.2.15-69.el6.centos.x86_64
--> Processing Dependency: apr-util-ldap for package: httpd-2.2.15-69.el6.centos.x86_64
--> Running transaction check
---> Package apr-util-ldap.x86_64 0:1.3.9-3.el6_0.1 will be installed
---> Package httpd-tools.x86_64 0:2.2.15-69.el6.centos will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package             Arch         Version                      Repository  Size
================================================================================
Installing:
 httpd               x86_64       2.2.15-69.el6.centos         base       836 k
Installing for dependencies:
 apr-util-ldap       x86_64       1.3.9-3.el6_0.1              base        15 k
 httpd-tools         x86_64       2.2.15-69.el6.centos         base        81 k

Transaction Summary
================================================================================
Install       3 Package(s)

Total download size: 932 k
Installed size: 3.2 M
Downloading Packages:
(1/3): apr-util-ldap-1.3.9-3.el6_0.1.x86_64.rpm          |  15 kB     00:00     
(2/3): httpd-2.2.15-69.el6.centos.x86_64.rpm             | 836 kB     00:00     
(3/3): httpd-tools-2.2.15-69.el6.centos.x86_64.rpm       |  81 kB     00:00     
--------------------------------------------------------------------------------
Total                                           1.9 MB/s | 932 kB     00:00     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : apr-util-ldap-1.3.9-3.el6_0.1.x86_64                         1/3 
  Installing : httpd-tools-2.2.15-69.el6.centos.x86_64                      2/3 
  Installing : httpd-2.2.15-69.el6.centos.x86_64                            3/3 
  Verifying  : httpd-tools-2.2.15-69.el6.centos.x86_64                      1/3 
  Verifying  : httpd-2.2.15-69.el6.centos.x86_64                            2/3 
  Verifying  : apr-util-ldap-1.3.9-3.el6_0.1.x86_64                         3/3 

Installed:
  httpd.x86_64 0:2.2.15-69.el6.centos                                           

Dependency Installed:
  apr-util-ldap.x86_64 0:1.3.9-3.el6_0.1                                        
  httpd-tools.x86_64 0:2.2.15-69.el6.centos                                     

Complete!
[root@host_C ~]# echo "THIS IS HOST_C" > /var/www/html/index.html
[root@host_C ~]# /etc/init.d/httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd: httpd: apr_sockaddr_info_get() failed for host_C
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
                                                           [  OK  ]
[root@host_C ~]# curl 192.168.0.13
THIS IS HOST_C
[root@host_C ~]# ss -ntl
State       Recv-Q Send-Q                                                     Local Address:Port                                                       Peer Address:Port 
LISTEN      0      511                                                                   :::80                                                                   :::*     
LISTEN      0      128                                                                   :::22                                                                   :::*     
LISTEN      0      128                                                                    *:22                                                                    *:*     
LISTEN      0      64                                                                    :::23                                                                   :::*     
[root@host_C ~]# 
      

  說明:我們在首頁上寫了THIS IS HOST_C,并開啟了http服務。可以看到80端口已經處于監聽狀态,首頁面也是可以正常通路。

[root@host_A ~]# ssh -D 2048 192.168.0.12 -fN
[email protected]'s password: 
[root@host_A ~]# ss -nt
State       Recv-Q Send-Q                                                     Local Address:Port                                                       Peer Address:Port 
ESTAB       0      0                                                           192.168.0.11:13558                                                      192.168.0.12:22    
ESTAB       0      52                                                          192.168.0.11:22                                                        192.168.0.232:8351  
[root@host_A ~]# ss -ntl
State       Recv-Q Send-Q                                                     Local Address:Port                                                       Peer Address:Port 
LISTEN      0      128                                                            127.0.0.1:2048                                                                  *:*     
LISTEN      0      128                                                                  ::1:2048                                                                 :::*     
LISTEN      0      128                                                                   :::22                                                                   :::*     
LISTEN      0      128                                                                    *:22                                                                    *:*    
      

  接下來我們啟動代理來通路下C

[root@host_A ~]# curl 192.168.0.13
curl: (7) couldn't connect to host
[root@host_A ~]# curl --socks5 127.0.0.1:2048 192.168.0.13 
THIS IS HOST_C
[root@host_A ~]# 
      

  說明:curl啟動代理需要加上 --socks5 來指定代理伺服器和端口,可以看到在沒有指定代理伺服器的時候,A是不能夠通路C的,指定了代理伺服器和端口就可以正常通路了。

總結:本地端口轉發和遠端端口轉發都需要指定目标主機的端口,通常我們轉發特定端口下的網絡資料可以用這兩種。動态端口可以實作socks代理進而實作加密以及突破防火牆對web浏覽器的限制。

作者:Linux-1874

出處:https://www.cnblogs.com/qiuhom-1874/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利.

繼續閱讀