今天用公司环境在测试网络隧道, 在写一半文章的时候突然老板来找我了, 我真的好苦啊!
和老板的对话记录
告警邮件
自己好苦命, 希望明天不要被怼的太惨.
好了, 让我们开始今天的内容.
你是否常常遇到这些个麻烦, 因为公司安全策略的问题, 每次要通过跳板机而不能直接连开发环境, 使用上面已经搭建好的数据库服务. 为了方便发布, 自己电脑上的服务别人, 不能让开发环境的机器直接连上测试. 还有我们在星巴克喝着咖啡连着免费 Wi-Fi 的时候, 会不会网络请求都被黑客抓包下来?
概述
SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据. 但是, SSH 还同时提供了一个非常有用的功能, 这就是端口转发. 它能够将其他 TCP 端口的网络数据通过 SSH 链接来转发, 并且自动提供了相应的加密及解密服务. 这一过程有时也被叫做 "隧道"(tunneling). 这是因为 SSH 为其他 TCP 连接提供了一个安全的通道, 避免了用户名, 密码以及隐私信息的明文传输. 例如, Telnet,SMTP,LDAP 这些 TCP 应用.
如果工作环境中的防火墙限制了一些网络端口的使用, 但是允许 SSH 的连接, 那么也是能够通过将 TCP 端口转发来使用 SSH 进行通讯. 总的来说 SSH 端口转发能够提供两大功能:
加密 SSH Client 端至 SSH Server 端之间的通讯数据.
突破防火墙的限制完成一些之前无法建立的 TCP 连接.
隧道
本地转发
当开发机的 MySQL 只能从跳板机连上, 我怎么才能跳过跳板机来访问远程 MySQL 呢?
访问远程服务器的 MySQL
如上图, 我们要明确的是现在有三个角色, 客户端(SSH Client), 跳板机(SSH Server), 和服务器.
客户端只能通过 SSH 连接到跳板机上, 跳板机可以直接访问服务器的全部端口, 服务器中安装了 MySQL 服务并监听了 3306 端口.
这个时候, 我们肯定是要用本地转发来连接, 命令规则如下
SSH -L [local host:]<local port>:<remote host>:<remote port> <SSH hostname>
看起来非常的令人费解, 不清楚的问题不过就是三个, what? where? how?
what : 使用本地转发, 监听本地的某个端口, 当应用访问这个端口的时候, SSH 会将请求截取到, 通过跳板机作为中间媒介, 转发到服务器上. 服务器处理完成后, 数据再原路返回完成整个链路. SSH 服务在这个过程中完成了加密, 转发, 解密, 通讯的操作.
where : 在客户端 (也称本地, SSH Client) 上做这个事情
how : 使用以下命令配置, 就可以达到访问本地 9527 端口转发到服务器的 3306 端口啦
SSH -L 9527: 服务器: 3306 root@跳板机
解释为, 当访问本机的 9527 的端口时, 被加密后转发到跳板机的 SSH 服务, 服务器的 3306 端口
注意的点
SSH 端口转发是通过 SSH 连接建立起来的, 我们必须保持这个 SSH 连接以使端口转发保持生效. 一旦关闭了此连接, 相应的端口转发也会随之关闭. SSH -g -L <local port>:<remote host>:<remote port> <SSH hostname>
我们只能在建立 SSH 连接的同时创建端口转发, 而不能给一个已经存在的 SSH 连接增加端口转发.
好了, 我们已经在本地 建立了端口转发, 那么既然我们在监听本地的 9527 端口, 那么其他机器也访问本地的 9523 端口会不会自动转发呢? 比如能否新增加一台客户端 2 来直接连接客户端的 9527 端口? 答案是不行的, 在主流 SSH 实现中, 本地端口转发绑定的是 lookback 接口, 这意味着只有 localhost 或者 127.0.0.1 才能使用本机的端口转发 , 其他机器发起的连接只会得到 "connection refused.". 好在 SSH 同时提供了 GatewayPorts 关键字, 我们可以通过指定它与其他机器共享这个本地端口转发.
当然了, 你可以随意的指定 remote host, 假如你要访问的服务就在跳板机上, 因为防火墙又不能直接访问到, 那么 remote host 和 SSH hostname 可以是同一台
远程转发
我的开发机上部署了一个 MySQL 服务, 我想回家以后还是连上我处于内网开发机上的 MySQL 服务, 这个时候我们怎么弄呢?
远程转发图示
我们需要借助一台公网的服务器讲远程的流量转发过来, 由于安全策略内网机器可以连通外网机器, 但是外网不能访问内网机器. 我们只要转发远程的请求到正确的内网的服务上就可以了. 它的命令格式是:
SSH -R [SSH server host:]<SSH server port>:<local host>:<local port> <SSH hostname>
what : 使用远程转发, 监听公网服务器的某个端口, 当应用访问这个端口的时候, SSH 会将请求截取到, 通过 SSH 客户端作为中间媒介, 转发到真实提供服务的服务器上. 服务器处理完成后, 数据再原路返回完成整个链路.
where : 在内网服务器上运行此命令
how : 使用以下命令配置, 就可以达到访问外网机器 9527 端口转发到内网服务器的 3306 端口啦
SSH -R 9527: 内网机器: 3306 root@公网机器
让公网服务器监听 9527 端口的访问, 如有访问, 就加密后通过 SSH 服务转发请求到内网机器 SSH 客户端, 再由内网机器 SSH 客户端解密后转发到内网机器 3306 端口. 这听起来有点奇怪, 因为这个时间内网服务器充当了两个角色, 就是 SSH 客户端和 server 端. 用下图的展示看起来更直观一点
有跳板机的远程转发
这个时候我们就可以在跳板机上使用命令
SSH -R 9527: 内网机器: 3306 root@公网机器
这个时候就是让公网服务器监听 9527 端口的访问, 如有访问, 就加密后通过 SSH 服务转发请求到跳板机 SSH 客户端上, 再由 SSH 客户端解密后转发到内网机器 3306 端口上.
注意的点
必须保持 SSH client 到 SSH server 的 SSH 连接以使端口转发保持生效. 一旦关闭了此连接, 相应的端口转发也会随之关闭.
我们只能在建立 SSH 连接的同时创建端口转发, 而不能给一个已经存在的 SSH 连接增加端口转发.
对于远程转发来说,
/etc/SSH/sshd_config
里要把 AllowTcpForwarding 选项设置为 yes, 否则 - R 远程端口转发会失败. 把 / etc/sysctl.conf 里的
net.ipv4.ip_forward = 0
设置为 1
默认转发到远程主机上的端口绑定的是 127.0.0.1, 如要绑定 0.0.0.0 需要把
/etc/SSH/sshd_config
里的 GatewayPorts 选项设置为 yes. 这个选项如果由于权限没法打开也有办法, 可配合 SSH -L 将端口绑定到 0.0.0.0, 如下 SSH -R 127.0.0.1:9527: 内网机器: 3306 root@公网机器
SSH -L 0.0.0.0:9527:127.0.0.1:9527 root@127.0.0.1
本地转发与远程转发的区别与共同点
共同点:
都要保持 SSH 不要断掉
都是在建立链接的同时创建端口转发
都是转发请求
都是在 SSH client 上运行
区别:
本地转发是 SSH client 就是 client, 远程转发 SSH client 是 server
本地转发是本地请求远程的服务, 远程转发是远程请求本地的服务
实在理不清, 听我的, 转发是指转发请求, 本地转发就是把本地的请求转发出去; 远程转发就是把远程的请求转发过来.
动态转发
我有一台香港服务器能上外网, 凭什么我自己不能上外网! 还真就可以.
前面我们已经讨论过了本地转发, 远程转发, 但是前提都是要求有一个固定的应用服务端的端口号. 那如果没有端口号怎么办? 等等, 什么样的应用会没有这个端口号呢? 嗯, 比如说用浏览器, 比如说 MSN 等等.
同时当我们在一个不安全的 Wi-Fi 环境下上网, 用 SSH 动态转发来保护我们的网页浏览及 MSN 信息无疑是十分必要的.
让我们先来看一下动态转发的命令格式:
SSH -D <local port> <SSH Server>
动态转发
实际使用如下
SSH -qTFnN -D 127.0.0.1:9527 root@香港服务器
怎么使用
在浏览器里设置使用 socks5 代理 127.0.0.1:9527, 然后浏览器就可以访问 host1 所在网络内的任何 IP 了. 推荐 Chrome 浏览器 switchyOmega 插件设置为下就可以了.
switchyOmega
如果是普通命令行应用, 使用 proxychains-ng, 参考命令如下:
- brew install proxychains-ng
- VIM /usr/local/etc/proxychains.conf # 在 ProxyList 配置段下添加配置 "socks5 127.0.0.1 9527"
- proxychains-ng wget http://host2 # 在其它命令行前添加 proxychains-ng 即可
如果是 SSH, 则用以下命令使用 socks5 代理: SSH -o ProxyCommand='/usr/bin/nc -X 5 -x 127.0.0.1:5000 %h %p' user@host2 转发常用的参数用法 SSH -qTfnN -D 127.0.0.1:12345 test@222.333.444.555
-f 要求 SSH 在执行命令前退至后台. 它用于当 SSH 准备询问口令或密语, 但是用户希望它在后台进行. 该选项隐含了 - n 选项.
-N 不执行远程命令. 用于转发端口.
-C 要求进行数据压缩 (包括 stdin, stdout, stderr 以及转发 X11 和 TCP/IP 连接 的数据). 压缩算法和 gzip(1)的一样, 协议第一版中, 压缩级别 "level" 用 CompressionLevel 选项控制. 压缩技术在 modem 线路或其他慢速连接上很有用, 但是在高速网络上反而 可能降低速度. 可以在配置文件中对每个主机单独设定这个参数.
-g 允许远端主机连接本地转发的端口
-q 安静模式. 消除所有的警告和诊断信息
-T 禁止分配伪终端
-n 把 stdin 重定向到 / dev/null (实际上防止从 stdin 读取数据). SSH 在后台运行时一定会用到这个选项. 它的常用技巧是远程运行 X11 程序.
引用
实战 SSH 端口转发
jeremy 的技术点滴
SSH 端口转发
SSH 隧道与代理
SSH 记 SSH 的几种玩法 https://www.cnblogs.com/adislj777/p/6178845.html
(本故事纯属虚构, 如有雷同纯属巧合)
来源: https://www.qcloud.com/developer/article/1424244