SSH 代理设置

2015-01-18 Sunday     linux , misc

通过 ssh 的端口转发或者隧道 (tunneling) 功能,可以实现: A) 加密 SSH Client 端至 SSH Server 端之间的通讯数据;B) 突破防火墙的限制完成一些之前无法建立的 TCP 连接。

简介

首先看下,对于转发有些比较有用的参数:

  • -N 告诉 SSH 客户端,这个连接不需要执行任何命令,也就是说不需要打开远程 shell,仅仅做端口转发;
  • -T 不为这个连接分配 TTY。其中 -N,-T 两个参数可以放在一起用,代表这个 SSH 连接只用来传数据,不执行远程操作;
  • -f 告诉SSH客户端在后台运行,要关闭这个后台连接,就只有用 kill 命令去杀掉进程;
  • -L 做本地映射端口,需要注意被冒号分割的三个部分含义,下面做详细介绍;
  • -C 压缩数据传输;
  • -g (GatewayPorts) 默认只转发本地发送的数据,如果要转发其它服务器的客户端请求,则需要添加该参数。

接下来,看看具体的使用场景,以及配置方式。

本地转发

其中,通过本地转发时,命令参数如下。

----- 本地转发方式的参数设置
$ ssh -N -f -L [local port]:[local host]:[remote port] [user@remote host]

其中 -L X:Y:Z 参数的含义是:将 IP 为 Y 的机器的 Z 端口通过中间服务器 (部署了 sshd 的服务器) 映射到本地机器的 X 端口。

需要注意的是,此是只有 ssh 客户端与服务器之间的数据是加密的,而实际上 中间服务器到 Y 服务器的数据没有加密

转发到本地服务

为了防止被攻击,通常在进行防火墙配置时,会尽可能减小打开的端口,例如只开启 80/443 服务端口,因此如果需要访问 mysql(3306) 服务只能从本地访问,此时可以使用该功能。

可以执行如下命令,然后访问本地的端口 7000 即可。

----- 本地执行如下命令,然后访问localhost:7000即可
$ ssh -N -f -L 7000:localhost:3306 mysql_server_ip

----- 访问远程的MySQL服务
$ mysql -P7000 -hlocalhost

注意,非管理员只能使用 1024~65535 的端口,在此选择 7000 端口。

数据在传输时将会通过如下的四步:A) 将数据发送到本地的 7000 端口;B) 本地的 SSH Client 将 7000 收到的数据加密后发送到 mysql_server_ip;C) SSHD 端收到数据后解密,并发送给本地的 3306 端口;D) 从 MySQL Server 上返回的数据按照原路返回。

转发到其它服务器

另外一种场景如下,A 尝试访问 C 提供的 FTP 服务,但是由于防火墙导致不能直接访问,也就是说 ABC 链路不通。但是 ABD 链路是通的,而且 D 上运行着 ssh-server,此时就可以利用隧道技术建立 ABDC 链路。

SSH Tunneling Local

也就是说,中间服务器 D 部署着 sshd 服务,用于建立 ssh 连接;C 的 21 端口提供 FTP 服务,然后就可以通过如下方式建立隧道。

----- 本地执行如下命令,然后访问localhost:2121即可
$ ssh -N -f -L 2121:234.234.234.234:21 123.123.123.123

----- 访问234.234.234.234服务器上的ftp服务
$ ftp localhost:2121

远程转发

对于上述的第二个场景,A 通常时一个内网,也就是说 D-B-A 是无法建立链接的,如上所述,而 A-B-D 是可以通过 ssh 建立链接的,为了可以建立 D-B-A 的连接,那么就需要远程转发了。

也就是说,我们利用一条已经连接好的 A-B-D 方向的连接来完成 D-B-A 方向的访问。

$ ssh -R [local port]:[remote host]:[remote port] [SSH hostname]

----- 在123.123.123.123上执行如下命令,建立22(ssh服务)的远程转发
$ ssh -N -f -R 2222:127.0.0.1:22 123.123.123.123

----- 反向登陆到D上
$ ssh -p 2222 localhost 

此是的操作为让 SSH hostname 监听自己的 local port 端口;将所有的数据经由 123.123.123.123 服务器,转发到 remote host:remote post 服务器。

对于 D 来说,A 是一台远程主机,所以这种情况就被称为 “远程端口绑定” 。

两者比较容易混淆,可以通过如下的方法区分。如果服务器(ssh和应用)都在同一端,则是本地转发;否则是远程转发。

另外,需要注意,”远程端口转发” 的前提条件是,D 和 A 两台主机都有 sshd 和 ssh 客户端。

另外示例

也可以理解为,A 提供了一个服务,D 想要访问这个服务,但是 A 没有公网 IP,导致 D 无法直接访问。

此时就需要建立一个 A->D 的隧道,然后 D 通过这个隧道访问即可。

A SVR(ssh-CLI) 172.16.0.163
D CLI(ssh-SVR) 192.168.9.15

ssh -N -f -R 3967:127.0.0.1:3967 root@192.168.9.15

动态转发

也就是通过 ssh 在本地建立一个 socks 代理服务,所有的本地网络访问都会通过该端口,然后转发到服务器,而应用程序决定使用那个端口。其大致的工作如下:

SSH Tunneling Sock

翻墙过程如下:

  1. 首先,墙内的客户机跟墙外的代理服务器,建立好 SSH 连接,并设定动态绑定;

  2. 此时墙内客户机上的 SSH 会监听本地的一个端口 7001;

  3. 当访问 www.google.com 时,会将请求发送到 7001 端口,SSH 将此请求通过 SSH 加密连接发送到墙外服务器的 SSH 上;

  4. 由于建立的时候是动态绑定,服务器会将相应的请求发送到 www.google.com 的 80 端口,并在收到回复后,原路返回给客户机的 SSH,客户机的 SSH 返回给应用程序。

所以在上述的模型中,客户机的 SSH 实际上就是实现了一个 SOCKS 代理的角色,这个 SOCKS 代理侦听了 7001 端口,并将所有的请求都代理给服务器的 SSH,并利用 SSH 动态绑定,让服务器进一步转发请求。

当然,使用时,需要在浏览器或者其他应用程序上设置 SOCKS 代理,实际设置 SOCKS-v4 就可以,而 SOCKS-v5 仅仅增加了鉴权功能,代理指向 127.1:7001 即可。

$ ssh -D [local port] [SSH Server]
$ ssh -D 7000 [SSH Server]

$ ssh -N -f -D 1080 foobar@123.123.123.123          # 将端口绑定在127.0.0.1上
$ ssh -N -f -D 0.0.0.0:1080 123.123.123.123         # 将端口绑定在0.0.0.0上

上述的命令,建立一个通过 SOCK5 协议的 123.123.123.123 的 SOCKS 服务器。

X 协议转发

暂时没有仔细研究

参考

关于转发认证,可以参考 An Illustrated Guide to SSH Agent Forwarding,或者参考 本地文档



如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^


About This Blog

Recent Posts

Categories

Related Links

  • RTEMS
    RTEMS
  • GNU
  • Linux Kernel
  • Arduino

Search


This Site was built by Jin Yang, generated with Jekyll, and hosted on GitHub Pages
©2013-2019 – Jin Yang