Linux

使用多跳 ssh 隧道訪問數據庫

  • July 3, 2020

我們有一些只能通過跳轉主機訪問的遠端伺服器。在這個遠端伺服器上執行 vms,它託管我想在本地訪問的數據庫。每個盒子都是一個linux系統。我在本地電腦、遠端主機及其虛擬機上只有 su 權限。

這意味著我們的設置如下所示:

My local pc --> jumphost --> remotehost --> vm with mysql on 127.0.0.1:3306

通常我會 ssh 三次,然後使用 mysql cli。

現在我需要設置一條從我的本地電腦到託管數據庫的盒子的隧道。

Ulitmatly 我想使用類似 python lib ssh-tunnel及其類 SSHTunnelForwarder 的東西。但我想從 bash 命令開始設置這種代理。

ssh 身份驗證是基於密碼的,每個躍點需要不同的使用者。理想情況下,該解決方案不需要更改 ~/.ssh/config

我找到了這篇文章,我認為選項 3 非常接近我的需要。

一個例子來說明清楚。假設 jumphost 是:user1@192.168.11.29,我的 remotehost 是user2@172.1.1.1,帶有數據庫的 vm 是user3@10.100.1.1

我會嘗試的是:

ssh -L 9998:172.1.1.1:22 -N user1@192.168.11.29

從我的本地 pc 埠 9998 到遠端主機上的埠 22 的隧道

這裡開始我的問題,我將如何指定用於 ssh 隧道旁邊的使用者。任何人都可以引導我走向正確的方向嗎?

ssh -L 9999:10.100.1.1:22-N -p 9998 user2@localhost

從我的本地 pc 埠 9999 通過第一條隧道到遠端主機上的埠 22 的隧道

ssh -L 10000:locahost:3306 -N -p 9999 user3@localhost

從本地 pc 埠 10000 通過埠 9999 上的隧道到 vm 上的埠 3306 的隧道。

之後,據我所知,我應該能夠從我的本地 pc 訪問具有 127.0.0.1:3306 的 vm 上的數據庫。

我希望這是有道理的,我感謝每一個答案。

我能夠解決它,感謝這篇文章

class TunnelNetwork(object):
   def __init__(self, tunnel_info, target_ip, target_port):
       self.tunnel_info = tunnel_info
       self.target_ip = target_ip
       self.target_port = target_port


   def start_tunnels(self):
       self.tunnels = []
       for idx, info in enumerate(self.tunnel_info):
           # if we're not the first element, set the bastion to the local port of the previous tunnel
           if idx > 0:
               info['ssh_address_or_host'] = ('localhost', self.tunnels[-1].local_bind_port)
           # if we are the last element, the target is the real target
           if idx == len(self.tunnel_info) - 1:
               target = (self.target_ip, self.target_port)
           # else, the target is the next bastion
           else:
               if isinstance(self.tunnel_info[idx+1]['ssh_address_or_host'], tuple):
                   target = self.tunnel_info[idx+1]['ssh_address_or_host']
               else:
                   target = (self.tunnel_info[idx+1]['ssh_address_or_host'], 22)

           self.tunnels.append(SSHTunnelForwarder(remote_bind_address=target, **info))
           try:
               self.tunnels[idx].start()
           except:
               return False

       return True

   def stop_tunnels(self):
       for tunnel in reversed(self.tunnels):
           tunnel.stop()    


   def are_tunnels_active(self):
       return self.tunnels and all([t.is_active for t in self.tunnels])


   def get_local_connect_port(self):
       if self.tunnels:
           return self.tunnels[-1].local_bind_port
       else:
           return None

並將其用於:

tunnel_i = [
   {"ssh_address_or_host": "192.168.11.29",
    "ssh_username": "user1",
    "ssh_password": "",
   },
   {"ssh_address_or_host": "172.1.1.1 ",
    "ssh_username": "user2",
    "ssh_password": "",
   },
   {"ssh_address_or_host": "10.100.1.1",
    "ssh_username": "user3",
    "ssh_password": "",
   }
]

target_ip = "127.0.0.1"
target_port = 3306

tn = TunnelNetwork(tunnel_i, target_ip, target_port)

tn.start_tunnels()

確保在您使用的每個躍點上將 AllowTcpForwarding 設置為 On。

引用自:https://serverfault.com/questions/982014