Sshtunnel, SSH 隧道穿墙通内网利器

​ssh是Uinx派系系统中通用的管理接口协议,默认端口22。这个协议稳定而且通用性强,过防火墙、过检测、过中间人嗅探那是一等一的尖端,而且,机构内部基本对此协议通行无阻,实乃红队(攻方)穿墙越网之居家必备。

用ssh 命令当做流量和端口转发完全可以利用上面的优势,就是密令复杂了一点。下面介绍的这个工具Sshtunnel,是Python的一个安装包,它不仅能直接以命令行方式实现流量转发,还有更强大的编程功能。

A.安装:

sshtunnel是PyPI维护的包, 也就是说,简单地用python包安装命令就能安装:

pip install sshtunnel

或者

easy_install sshtunnel

或者

conda install -c conda-forge sshtunnel

源码安装,先从这里(https://github.com/pahaz/sshtunnel)下回来,然后运行:

python setup.py install


B.使用场景:

使用sshtunnel的一个经典场景,就如下面图形描述的那样。用户可能需要访问远程服务器(例如8080端口),但是你只能访问这台远程服务器的SSH端口(通常是22端口)

图1:如何通过ssh绕过防火墙去访问一个不能直接访问的服务

如果能操纵SSH服务器,还可以访问到本地客户端看不到的私有的服务器(远程服务器的角度)

图2:如果通过SSH 隧道访问私有服务器

C.用例:

API不仅允许初始化渠道后直接启动,还允许使用“with”语境,这会贯穿从隧道启动到关闭的整个过程。

案例1

上面图1的例子,假如远程服务器的地址是:"pahaz.urfuclub.ru",使用密码认证,然后随机指定本地绑定的端口。

from sshtunnel import SSHTunnelForwarder

server = SSHTunnelForwarder(

    'pahaz.urfuclub.ru',

    ssh_username="pahaz",

    ssh_password="secret",

    remote_bind_address=('127.0.0.1', 8080)

)

​server.start()

​print(server.local_bind_port)  # show assigned local port

# work with `SECRET SERVICE` through `server.local_bind_port`.

​server.stop()


案例2:

上面图2的例子,不能直接访问的私有服务端口转发案例,假如只能使用证书访问,远程SSH服务器只有443端口没被左边的防火墙拦截。

import paramiko

import sshtunnel​

with sshtunnel.open_tunnel(

    (REMOTE_SERVER_IP, 443),

    ssh_username="",

    ssh_pkey="/var/ssh/rsa_key",

    ssh_private_key_password="secret",

    remote_bind_address=(PRIVATE_SERVER_IP, 22),

    local_bind_address=('0.0.0.0', 10022)

) as tunnel:

    client = paramiko.SSHClient()

    client.load_system_host_keys()

    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    client.connect('127.0.0.1', 10022)

    # do some operations with client session

    client.close()

​print('FINISH!')


案例3

Mysql 3306端口转发:

from sshtunnel import open_tunnel

from time import sleep

​with open_tunnel(

    ('localhost', 2222),

    ssh_username="vagrant",

    ssh_password="vagrant",

    remote_bind_address=('127.0.0.1', 3306)

) as server:

​    print(server.local_bind_port)

    while True:

        # press Ctrl-C for stopping

        sleep(1)

print('FINISH!')


或者简单的一条命令:


(bash)$ python -m sshtunnel -U vagrant -P vagrant -L :3306 -R 127.0.0.1:3306 -p 2222 localhost


案例4

启动一个跳跨两个隧道的ssh session。SSH 传输和隧道都是以后台形式运行,它不会在连接关闭时退出进程。

import sshtunnel

from paramiko import SSHClient

​​with sshtunnel.open_tunnel(

    ssh_address_or_host=('GW1_ip', 20022),

    remote_bind_address=('GW2_ip', 22),

    block_on_close=False

) as tunnel1:

    print('Connection to tunnel1 (GW1_ip:GW1_port) OK...')

    with sshtunnel.open_tunnel(

        ssh_address_or_host=('localhost', tunnel1.local_bind_port),

        remote_bind_address=('target_ip', 22),

        ssh_username='GW2_user',

        ssh_password='GW2_pwd',

        block_on_close=False

    ) as tunnel2:

        print('Connection to tunnel2 (GW2_ip:GW2_port) OK...')

        with SSHClient() as ssh:

            ssh.connect('localhost',

                port=tunnel2.local_bind_port,

                username='target_user',

                password='target_pwd',

            )

            ssh.exec_command(...)



命令行使用帮助:

$ sshtunnel --help


.>勒索软件绕过安全监测的那些套路

.>手把手,远程桌面客户端提取明文账号密码

.> 一种通用的Docker提权方式

推荐阅读更多精彩内容