【问题标题】:Remote port forwarding with paramiko使用 paramiko 进行远程端口转发
【发布时间】:2017-01-22 15:17:57
【问题描述】:

如何使用 Paramiko 实现远程端口转发?我见过做本地端口转发的例子,但这让我很困惑。我想实现

ssh -N -R 2210:localhost:5000 username@remotehost

与帕拉米科。 (将 remotehost 端口 2210 转发到 localhost 端口 5000,不允许打开 shell)。我试过了

ssh=paramiko.SSHClient()
ssh.connect(remotehost, username=remoteusername, key_filename="/....")
transport = ssh.get_transport()
transport.open_channel(......)

但 dest_addr、src_addr 和操作(direct-tcpip、forwarded-tcpip)的所有组合似乎都无法引发 ChannelException(管理禁止)。我的命令行 ssh 有效,所以我有权这样做,但我不知道如何执行 Paramiko 实现。

有什么想法吗?

汉努

【问题讨论】:

  • 我当然可以恢复为 subprocess.Call 并执行 ssh 但我想将其保留在代码中以帮助监控连接状态。
  • 这个答案为我解决了这个问题:stackoverflow.com/questions/11294919/…

标签: python paramiko portforwarding


【解决方案1】:

Sample script 展示了如何通过 paramiko 进行远程端口转发。 此脚本连接到请求的 SSH 服务器并设置远程端口 通过隧道从远程端口转发(openssh -R 选项) 连接到可从本地机器访问的目的地。

示例:ssh -R 4000:internal.example.com:80 public.example.com

import socket
import select
import sys
import threading

import paramiko


def handler(chan, host, port):
    sock = socket.socket()
    try:
        sock.connect((host, port))
    except Exception as e:
        print("Forwarding request to %s:%d failed: %r" % (host, port, e))
        return

    print(
        "Connected!  Tunnel open %r -> %r -> %r"
        % (chan.origin_addr, chan.getpeername(), (host, port))
    )
    while True:
        r, w, x = select.select([sock, chan], [], [])
        if sock in r:
            data = sock.recv(1024)
            if len(data) == 0:
                break
            chan.send(data)
        if chan in r:
            data = chan.recv(1024)
            if len(data) == 0:
                break
            sock.send(data)
    chan.close()
    sock.close()


def reverse_forward_tunnel(server_port, remote_host, remote_port, transport):
    transport.request_port_forward("", server_port)
    while True:
        chan = transport.accept(1000)
        if chan is None:
            continue
        thr = threading.Thread(
            target=handler, args=(chan, remote_host, remote_port)
        )
        thr.setDaemon(True)
        thr.start()


def main():
    """
    ssh -R 4000:internal.example.com:80 public.example.com
    """
    ssh_host = 'public.example.com'
    ssh_port = 22
    ssh_user = 'root'
    ssh_pass = 'password'
    remote_bind_port = 4000  # port on server to forward
    forward_host = 'internal.example.com'  # dest host to forward to
    forward_port = 80  # dest port to forward to

    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.WarningPolicy())

    try:
        client.connect(
            ssh_host,
            ssh_port,
            username=ssh_user,
            password=ssh_pass,
        )
    except Exception as e:
        print("*** Failed to connect to %s:%d: %r" % (ssh_host, ssh_port, e))
        sys.exit(1)

    print(
        "Now forwarding remote port %d to %s:%d ..."
        % (remote_bind_port, forward_host, forward_port)
    )

    try:
        reverse_forward_tunnel(
            remote_bind_port, forward_host, forward_port, client.get_transport()
        )
    except KeyboardInterrupt:
        print("C-c: Port forwarding stopped.")
        sys.exit(0)


if __name__ == "__main__":
    main()

【讨论】:

    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    • 2012-09-03
    • 2013-05-16
    • 1970-01-01
    相关资源
    最近更新 更多