使用 SSH 建立 socks 代理进行内网穿透

点击阅读

0x01 前言

SSH (Secure Shell) 是一种加密网络协议,用于在不安全的网络上安全地运行网络服务。

OpenSSH 是用于使用 SSH 协议进行远程登录的主要连接工具。对所有流量进行加密,此外,OpenSSH 还提供了一整套安全的隧道功能,多种身份验证方法以及复杂的配置选项。

在一般的 Linux 机器中默认都会装有 OpenSSH,那么在偶尔需要建立代理访问内部网络的时候,抛弃一些其它代理程序的繁琐配置,使用 ssh 不失为一种方便快捷的办法

OpenSSH 命令手册: ssh(1) - OpenBSD manual pages

0x02 准备

ssh 配置文件 /etc/ssh/sshd_config 中默认没有 GatewayPorts 这一项或者值为 no

GatewayPorts 用于指定是否允许远程主机连接到为客户端转发的端口,参数为 no 强制远程端口转发仅对本地主机可用,即将远程端口转发绑定到环回地址,防止其他远程主机连接,yes 强制强制远程端口转发绑定到通配符地址,或者指定的其他地址

根据情况进行合理配置,比如要在公网做转发的时候就需要配置 GatewayPorts yes

sshd_config 配置参数手册:sshd_config —— OpenSSH daemon configuration file

0x03 转发

在本地使用 Docker 模拟搭建一个简易的网络环境

image-20200203005152618

如图,都是在内网中的机器,只不过网段不同,使用 ssh 建立代理来访问不同层次的网络

下面先简单介绍用到的命令参数:

1
2
3
4
5
6
7
8
9
10
-p port 连接到远程主机上的端口
-N 不执行远程命令。对于仅转发端口很有用
-f 将 ssh 命令放在后台
-n 从 /dev/null 重定向标准输入(实际上,防止从标准输入读取),在后台运行ssh时必须使用此选项
-q 安静模式。阻止大多数警告和诊断消息。
-g 允许远程主机连接到本地转发的端口
-T 禁用伪终端分配
-p [port] 要连接到远程主机上的端口
-D [bind_address:]port 指定本地“动态”应用程序级端口转发
-R [bind_address:]port:host:hostport 指定与远程(服务器)主机上给定的TCP端口或Unix套接字的连接将转发到本地

应用场景 一. Host 1 访问 192.168.1.0/24 网络

图中的 Host 1 有且只有一个 ip,处于 172.16.1.0/24 网络中,能直接访问的主机只有 Host 2

在 Host 1 使用 ssh 建立一个 socks 代理服务器即可,使用 -D

-D 参数是比较关键的一个,建立代理就靠它了,通过分配一个套接字来侦听本地端的端口,每当与此端口建立连接时,该连接都会通过安全通道转发,充当 SOCKS 服务器,支持 SOCKS4 和 SOCKS5 协议

只有root可以转发特权端口(端口号小于 1024 的端口),动态端口转发也可以在配置文件中指定。

Host 1 执行命令:

ssh -fnqgNTD [host 1 port ] -p 22 [host 2 username]@[host 2 ip]

该场景下使用:ssh -fnqgNTD 7777 -p 22 j0k3r@172.16.1.3

Host 1 给当前终端设置 socks 5 代理:export ALL_PROXY=socks5://127.0.0.1:10808

访问 192.168.1.0/24 网络验证一下

image-20200204000948914

Host 1 发送的网络数据通过 socks 代理和 ssh 连接发送到了 Host 2,于是就能访问 Host 3 的服务了

引用场景 二. Host 1 访问 10.1.1.0/24 网络

上图可以看出 Host 2 和 Host 3 同处于 192.168.1.0/24 网络,但是只有 Host 3 还可以访问 10.1.1.0/24,而 Host 1 更是不能直接访问 Host 3,这个时候相对于场景一只需要在中间让 Host 2 把 Host 3 的 22 端口转发给 Host 1 就行了,最终使用场景一中的方法开启代理即可

需要用到 ssh 反向代理,使用 -R

-R 参数是转发的关键参数, 指定与远程(服务器)主机上给定的TCP端口或Unix套接字的连接将转发到本地

1
2
3
4
5
-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket
-R [bind_address:]port

举个例子

Host 2: ssh -fnqgNTR [host 1 port]:[host 3]:[host 3 port] -p 22 [host 1 username]@[host 1 ip]

该命令会将 host 3 的 port 转发到 host 1 的 port

该场景下命令为:ssh -fnqgNTR 6666:192.168.1.3:9090 -p 22 j0k3r@172.16.1.2

image-20200204003159932

此时 host 1 可以通过访问本地 6666 端口直接访问 host 3 的 9090 端口上的服务

同理,转发 host 3 的 ssh 端口,再建立代理

该场景下命令为:

Host 2: ssh -fngqNTR 7777:192.168.1.3:22 -p 22 j0k3r@172.16.1.2

Host 1: ssh -fngqNTD 6767 -p 7777 j0k3r@127.0.0.1, export ALL_PROXY=socks5://127.0.0.1:6767

此时 host 1 可以通过代理直接访问 host 4

image-20200204023545869

其他场景

(1)反向代理穿透内网,外网访问

image-20200204024355249

(2)正向代理

使用 -L

文章作者: J0k3r
文章链接: http://j0k3r.top/2020/01/08/ssh-proxy/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 J0k3r's Blog