利用SSH代理访问内网资源

前言

在实际网络环境中,很可能服务都是在内网环境,外网只暴露有限的端口,提供外网用户的访问。在这种场景下,在开发环境下直接访问内网环境是十分困难的。或者管理员在外网环境中,需要DEBUG内网服务。

这种需求你可能会想到端口映射或者VPN。

端口映射

更专业的术语叫DNAT,利用网络地址翻译技术,将内网的服务端口映射到外网ip上。这种技术更适合长期对外提供服务的需求使用,比如HTTP/FTP等服务在内网,希望暴露在互联网上,对于临时调试这种需求来说显得有些麻烦。另外,对于Hadoop集群这种严重依赖主机名通信的集群服务来说,很难通过端口映射让外网用户直接进行访问。

VPN

最近风口浪尖上的玩意,而且非常容易被ban掉。单就技术本身来说是非常有用的,提供了远程访问局域网的能力。但是这玩意配置和维护都相对复杂,需要专门搭建软件或硬件VPN服务器,有一定成本。适合长期稳定的从外网访问内网的需求使用。但是对于临时访问一下内网资源来说就有些重了。

本文我们分享一种更加轻量级的代理方式——SSH代理,可以帮助我们方便的利用SSH协议代理到内网环境中。

NOTE: 需要事先在内网环境中准备一个SSH跳板机,将ssh端口映射到外网上,以便外网可以通过SSH访问过来。

轻量级的代理方式——SSH

SSH是一种功能十分强大的协议,对于SA来说不可不熟悉。SSH除了最常见的远程连接到shell功能之外,还可以提供远程文件传输、端口转发、代理等多种功能。在Linux服务器中基本上已经默认预装了ssh服务,开箱即用。

SSH的-L与-D代理

SSH有三种代理参数-L,-D,-R-R代理不是本次重点,有兴趣的读者可以自行查阅man手册。

  • -L参数会在本地监听一个端口,转发数据到远程主机上。
    ssh -NL 3306:localhost:3306 user@remote_ip
    在本地监听一个3306端口,转发到远程主机上的localhost:3306上,等于访问本地的3306端口就相当于访问到了远程的mysql服务。这种方式访问远程服务会更安全,远程服务不需要对外网暴露端口。

很明显,这个代理只适用于代理单一ip单一服务的需求有用,本质上是反向代理,客户端不需要额外配置。

  • -D参数就厉害了,在本地开放一个socks5协议的代理端口,利用这个端口可以动态的访问到远程内网的环境。
    ssh -ND 1080 user@remote_ip
    这条命令会在本地开放一个1080socks5端口,支持socks5协议代理的应用程序就可以利用这个端口直接访问到内网资源。比如:
    curl --socks5 127.0.0.1:1080 localhost
    让curl命令利用socks5协议代理访问到远程服务器上的http服务,浏览器直接配置这个代理服务就可以无阻碍的访问到内网中所有的http服务了。

很明显,这个代理本质上是正向代理,可以实现一个代理访问更多服务资源的需求。但是需要客户端本身支持代理。

sshuttle

这是本文重点介绍的一个神器。回到我们之前hadoop集群(比如zookeeper集群、kafka集群等)的例子,这些集群没法通过单一的端口转发代理实现集群的访问,VPN有些太重,而且现在非常容易被ban。此时sshuttle进入我的视野,ubuntu下直接用sudo apt install -y sshuttle就可以安装了。这个工具非常巧妙,利用iptables的端口转发功能,直接把指定目标网络的请求通过ssh代理到远程,实现了非常类似于VPN的功能,但是几乎零配置,开箱即用,非常方便。不过只支持*nix环境的系统(如Linux, FreeBSD, MacOS等等)。

让我们先看一个简单的例子:

sshuttle -r user@remote_ip 10.0.0.0/8

代表将10.0.0.0/8这个网段的请求走SSH代理,是不是很容易使用?此外,还支持--dns,--auto-hosts, --auto-nets等十分有用的参数,根据实际情况去选用即可。

sshuttle实际体验上非常类似于VPN,但是比VPN更轻量,而且无需管理。值得注意的是,本质上这个工具是利用了端口转发的原理,并不是真正的VPN,所以对于ICMP这类的协议是没用的,也就是说,对于ping命令是无效的。

相关推荐