Home » ops » SSH隧道代理
SSH隧道代理

最近pypi镜像搭建好了,实际上pip本身有一个--proxy的指令,能够制定一个代理,就能完成内网机器无法通过pip访问外网资源的问题. 通过代理就能完成基本的下载包的需求了,而且其他的一些命令如gem,curl等等大多数常见的命令都支持走代理模式。

而且大家总在说 "用nginx做反向代理",那么到底什么代理,什么是反向代理呢?

正向代理

正向代理是客户端和服务器中间的服务器,为了从原始服务器取得内容,客户端向代理服务器发送一个请求并指定目标(原始服务器), 然后代理服务器向原始服务器转发请求并将获得的内容返回给客户端。

举个例子,比如正常情况下我没法办上youtube,但是我有个aws的机器,它不受GFW的限制,能够访问youtube,我也能正常访问那个aws的机器, 那么我通过发送请求给aws的机器,让他转发我的请求给youtube,然后把youtube返回的数据给我,我就能通过aws的机器作为跳板访问GFW, 那个aws的机器也就是代理服务器的角色,并且这种方式就是正向代理。

总结一下,正向代理就是我想访问一台机器,但是被墙了访问不到,我需要一台机器作为跳板转发我的请求。

反向代理

于正向代理不同,反向代理更多的是为了保护原始服务器。 对于客户端而言,反向代理中的代理服务器就是原始服务器,客户端并不需要知道有这个代理的角色存在, 因此客户端也不需要一些额外的设置,比如正向代理中制定代理服务器是谁。

比如在原始服务器A上配置防火墙,使得只有服务器B能够访问A,并且通过B服务器转发A的数据实现于外界的通信。这样对于客户端,它只需要和B交互, 从而隐藏了服务器A,B服务器也就是反向代理服务器。由于有代理服务器的存在,对于后面的原始服务器来说,也就多了一层做负载均衡的服务器。

透明代理

还有一种代理方式叫做透明代理,比如我实习的时候机器就不能上qq,这个就是透明代理,它在内网和外网之间捕捉用户的请求,过滤一部分请求。

SSH端口转发

有一种很简单的方式就能做到代理功能,那就是SSH本身提供的端口转发功能。 要想理解清楚SSH端口转发,首先必须记住这样几个原则:

本地转发

ssh本地转发命令为:

ssh -L <local port>:<remote host>:<remote port> <SSH hostname>

这条命令可以翻译成:从本地的端口发出请求,通过这台机器作为跳板转发请求到端口。 是相对而言的,比如是127.0.0.1的话,就是本身。 所以一般如果是127.0.0.1的话,跳板机或者代理服务器就是目标服务器。

举个例子:

  1. A是一台在我家的机器macbook air,它可以访问taobao,也就是服务器C
  2. B是一台在公司的机器imac,由于在公司的内网,所以在家的A访问不到B
  3. C是taobao的服务器,公司不让上taobao,所以服务器B访问不了C

现在要想在让B服务器能访问C的80端口,由于防火墙这条路本身是走不通的,但是由于B能访问A,A能访问C,所以能把A作为代理服务器实现这一要求。

在服务器B和服务器A之间建立ssh隧道,在SSH端口转发中,由于服务器B能连接到服务器A,并且请求是从服务器B发出,所以B既是ssh的client,也是请求的客户端 所以此时应该在B上去运行ssh的本地转发命令: ssh -L 8080:HOST_C:80 HOST_A

远端转发

ssh远端转发的命令为:

ssh -R <local port>:<remote host>:<remote port> <SSH hostname>

由于本身B是可以访问A的,但是A访问不到B,现在要想服务器A访问到B,也就是在家能连上公司的机器。

服务器B能连上A,所以B应该是ssh的client,此时请求是由A发起的,所以A是请求客户端,方向不同,所以是远端转发。 因此在B上运行命令: ssh -R 2222:127.0.0.1:22 HOST_A ,这里127.0.0.1是因为通过A服务器转发的目的服务器就是A本身。 这样在A上的2222端口就映射到了B的22端口。

动态转发

不管是本地转发还是远端转发,都需要一个具体的应用服务器的地址和端口号,要想访问其他机器的内容就得绑定很多条这样的转发命令, 通过动态转发就能省去这一个应用服务器的信息。

ssh -D <local port> <SSH Server>

当我们在一个不安全的 WiFi 环境下上网,用 SSH 动态转发来保护我们的网页浏览等信息无疑是十分必要的。 比如在本机运行: sh -D 7001 <SSH Server> 这样就相当于通过创建了一个SOCKS代理。

我们可以直接使用localhost:7001 来作为正常的 SOCKS 代理来使用,直接在浏览器上设置即可。 在 SSH Client 端无法访问的网站现在也都可以正常浏览。 而这里需要值得注意的是,此时 SSH 所包护的范围只包括从浏览器端(SSH Client 端)到 SSH Server 端的连接,并不包含从 SSH Server 端 到目标网站的连接。 如果后半截连接的安全不能得到充分的保证的话,这种方式仍不是合适的解决方案。

这个时候还可以在本机将SOCKS代理转成HTTP代理。 比如在本地安装polipo,修改polipo.conf文件,把SOCKS代理填上127.0.0.1:7001,然后 export http_proxy="127.0.0.1:8123" && export https_proxy="127.0.0.1:8123" 就在本地的8123端口起了一个http代理。

参考了IBM的实战 SSH 端口转发