原文:https://www.jianshu.com/p/388a93b1e7f7
https://blog.csdn.net/qq_34039315/article/details/77510923
首先你得XShell连接到一个其他服务器,然后才能用ssh的端口转发功能。
统一称使用的机器为本地机,连接到的服务器为远程机。
一、Local
这个配置是什么意思呢?
注意这个“类型方向”是Local(Outgoing),所以源主机的localhost指的是本地机,目标主机就是想要建立连接的目的。这个配置的现象就是:你在物理机浏览器输入 http://localhost:8018 就通过 远程机 访问了163.com这个地址。配置的意思就是:通过远程机,将163.com:80映射到物理机的8081端口。
这个有什么应用呢?
和代理差不多,就是将远程机作为一个跳板,将本地机与目标主机连接起来。
比如下图的例子,我想连接到 192.168.1.2怎么办?
我先连接到SSH Server,然后再修改上面的配置(源主机 localhost:8081,目标主机192.168.1.2),然后就能成功连接了(直接ssh连接本机的8081即可)。
二、Remote
这个配置是什么意思呢?
注意这个“类型方向”是Remote(Incoming),所以注意了!!!!源主机的localhost指的是远程机,目标主机的Localhost指的是物理机。这个配置的现象就是:你访问远程机的3000端口的时候,远程机自己将消息连接到了物理机的80端口来,看到的就是物理机80端口的内容。
这个有什么应用呢?
如下图所示,如果192.168.1.*是公司的网络,我白天在192.168.1.2机器上办公,我并不能登录SSH Server,晚上还想在家加会班怎们办呢?
分两步走:
1、首先192.168.1.2 ssh登录到10.10.10.10,然后配置(源主机 localhost:3333,目标主机localhost:22)
或者,在192.168.1.2配置如下也可以
ssh -N -f -R 3333:127.0.0.1:22 10.10.10.10
1
2、回家后ssh访问10.10.10.10的3333端口,即可访问到192.168.1.2了
---------------------
作者:乌枭
来源:CSDN
原文:https://blog.csdn.net/qq_34039315/article/details/77510923
版权声明:本文为博主原创文章,转载请附上博文链接!
-----------------------------------------------------------------------------------------------------------------------------------------------
使用 SSH TUNNEL 打通公司和家里的网络
前言
平时经常遇到下面的情况:
- 工作没做完,想回家继续做。带电脑回家?
- 碰到以前做过的功能,想从家里的电脑捞一点代码。没独立 IP 怎么访问?
- 服务器只允许公司网络访问,在外面要登服务器。找领导设置安全组权限(或者防火墙)?
- 在外面想访问公司局域网中的某个服务,比如
Gitlab
? - 公司网络不能逛淘宝?
- 想去墙外的世界看一看?
一般情况下的对应方法:
- 远程连接(比如Windows自带的)
- NAT内网穿透(比如花生壳,几年前用过免费版的,不太稳定,Linux下安装也不太顺畅)
- 一般需要正当理由
- 公司有固定公网 IP 的话,路由器设置端口转发,不过路由器权限呢?
- 代理服务器
- VPN(作用和代理服务器差不多,但原理不一样)
本文的目的就是使用 SSH TUNNEL
这项技术解决上面的问题,也就是打通所谓的 "公司内网" 和 "家庭内网"。
SSH TUNNEL
简介
经常远程连接 Linux 服务器的小伙伴,对于 ssh
这个命令应该不陌生吧。它还可以不执行远程指令只建立一条和远程服务器之间的连接,也就是形成了一条通道,在这条通道上我们就可以做一些文章了。
先看下 ssh
命令的参数介绍(需要了解更多请通过命令 man ssh
查看):
-1:强制使用ssh协议版本1;
-2:强制使用ssh协议版本2;
-4:强制使用IPv4地址;
-6:强制使用IPv6地址;
-A:开启认证代理连接转发功能;
-a:关闭认证代理连接转发功能;
-b:使用本机指定地址作为对应连接的源IP地址;
-C:请求压缩所有数据;
-F:指定ssh指令的配置文件;
-f:后台执行ssh指令;
-g:允许远程主机连接主机的转发端口;
-i:指定身份文件;
-l:指定连接远程服务器登录用户名;
-N:不执行远程指令;
-o:指定ssh客户端配置选项来覆盖配置文件中的配置,比如:-o "StrictHostKeyChecking no" 可以去除检查主机的提示;
-p:指定远程服务器上的ssh端口(默认为22);
-q:静默模式;
-X:开启X11转发功能;
-x:关闭X11转发功能;
-y:开启信任X11转发功能。
-D: 监听本地的指定端口,本机将作为 SOCKS5 服务器使用
-L: 本地监听指定端口,该端口收到的请求会通过远程服务器转发到另一台机器的指定端口上
-R: 远程服务器上监听指定端口,该端口收到的请求会通过本地转发到另一台机器的指定端口上
关键的就是最后的三个参数,对应 SSH 隧道
的三种端口转发模式:本地转发(-L Local),远程转发(-R Remote)和动态转发(-D Dynamic)
本地转发
本地监听指定端口,该端口收到的请求会通过远程服务器转发到另一台机器的指定端口上
- 语法:
ssh [-p ssh_port] -L [bind_address:]port:host:hostport user@remote_host
解释:
port:本地监听的端口
bind_address:监听端口使用的本地地址(如:192.168.1.2,127.0.0.1,0.0.0.0), 不设置默认为回环地址 127.0.0.1
host:转发的目标IP
hostport:转发的目标端口
注意:
host:hostport 是远程主机 user@remote_host:ssh_port 所能访问到的地址(包括 user@remote_host自己),本地主机不一定能访问该地址
- 示例:
ssh -p 23 -Nf -L 0.0.0.0:3000:123.123.123.124:3001 root@123.123.123.123
说明:
1. 通过 23 端口 ssh 远程服务器 123.123.123.123,使用帐号 root 登录
2. 本地监听端口 0.0.0.0:3000
3. 123.123.123.124 和 123.123.123.123 在一个局域网下,而本地不能直接访问 123.123.123.124
4. 123.123.123.124 主机通过 3001 端口开放服务
5. 调用链路:本地访问 --> 127.0.0.1:3000 -- ssh 隧道 --> 123.123.123.123 -- 转发 --> 123.123.123.124:3001
上面示例中相当于将远程主机 123.123.123.124 的 3001 端口映射为本地的 3000 端口,这样就可以通过局域网访问被限制的公网服务了。
远程转发
远程服务器上监听指定端口,该端口收到的请求会通过本地转发到另一台机器的指定端口上
- 语法:
ssh [-p ssh_port] -R [bind_address:]port:host:hostport user@remote_host
解释:
语法和 -L 一样,只不过监听侧和目标侧的网络对换而已
port:在远程主机 user@remote_host 上监听的端口
bind_address:远程主机 user@remote_host 监听端口使用的地址(如:remote_host,127.0.0.1,0.0.0.0)。
和 -L 有点区别,指定IP需要在远程主机上修改 /etc/ssh/sshd_config 中的配置:GatewayPorts。"yes" 表示 强制为 0.0.0.0; 默认为 "no" 表示强制为回环地址 127.0.0.1;"clientspecified" 表示由客户端决定
host:转发的目标IP
hostport:转发的目标端口
注意:
host:hostport 是本地主机所能访问到的地址(包括本机),远程主机 user@remote_host:ssh_port 不一定能访问该地址
- 示例:
ssh -p 23 -Nf -R 172.17.0.1:3000:192.168.1.100:3001 root@123.123.123.123
说明:
1. 通过 23 端口 ssh 远程服务器 123.123.123.123,使用帐号 root 登录
2. 123.123.123.123 监听端口 172.17.0.1:3000 (远程服务器运行 docker , 多了一个虚拟网络 172.17.0.0)
3. 192.168.1.100 和 本地主机 在一个局域网下,而 123.123.123.123(外网) 不能直接访问 192.168.1.100(内网)
4. 192.168.1.100 主机通过 3001 端口开放服务
5. 调用链路:远程服务器中访问 --> 172.17.0.1:3000 -- ssh 隧道 --> 本地 -- 转发 --> 192.168.1.100:3001
上面示例中相当于将局域网主机 192.168.1.100 的 3001 端口映射为远程服务器 123.123.123.123 的 3000 端口,这样就可以通过公网来访问局域网中的服务了。
动态转发
监听本地的指定端口,本机将作为 SOCKS5 服务器使用
- 语法:
ssh [-p ssh_port] -D [bind_address:]port user@remote_host
解释:
port:本地监听的端口
bind_address:监听端口使用的本地地址(如:192.168.1.2,127.0.0.1,0.0.0.0), 不设置默认为回环地址127.0.0.1
注意:
启动 socks5 代理
代理使用示例:
curl --socks5 bind_address:port baidu.com
- 示例
ssh -p 23 -Nf -D 127.0.0.1:3000 root@123.123.123.123
说明:
1. 通过 23 端口 ssh 远程服务器 123.123.123.123,使用帐号 root 登录
2. 本地监听端口 127.0.0.1:3000
3. 调用链路:本地局域网中访问任意http服务 -- 使用代理 --> 172.17.0.1:3000 -- ssh 隧道 --> 123.123.123.123 -- 转发 --> 目标http服务
上面示例中相当于开启了一个代理服务器,比起 本地转发
需要指定具体端口来说更加方便。
正文
上面已经介绍了 SSH TUNNEL
的使用方式,接下来就开始干正事了,先上两张网络拓扑图。
对比两张图把少的线连上就好了,是不是很easy?
原先环境:
三个独立的网络:公司内网、家里内网、阿里云专有网络,其中可以通过公司网络访问阿里云上的服务器而家里网络则不行。-
目标:
- 使家里网络的主机能访问公司内局域网中的主机
- 使家里网络的主机能访问公司阿里云上的服务器
-
预备工作:
- 有一台公网的服务器作为跳板机,公司和家里都能访问到(没有服务器?阿里云腾讯云学生机弄台玩玩)
- 因为
ssh
命令不能添加密码作为参数,只能手动输入,而且每次连接都要重新输入也不是很方便,这里采用公钥方式登录就可以免输密码了
# 创建ssh密钥对
ssh-keygen -t rsa -b 4096 -C "备注1" # 远程服务器上的 ~/.ssh/authorized_keys 权限要是600
# 追加本机公钥到远程服务器
cat ~/.ssh/id_rsa.pub | ssh -p 23 root@123.123.123.123 "cat - >> ~/.ssh/authorized_keys" # 或者直接复制本机公钥到远程服务器(会覆盖掉远程服务器已有的其他公钥)
scp -P 23 -p ~/.ssh/id_rsa.pub root@123.123.123.123:~/.ssh/authorized_keys -
步骤:
- 将【公司主机A】的端口【22】映射到【跳板机J】的端口【9999】上, 在【公司主机A】按照下面的命令配置(【跳板机J】需要按上文方式将
GatewayPorts
设为true
):
ssh -p 23 -Nf -R 9999:127.0.0.1:22 root@123.123.123.123
当然也可以通过
docker
来运行autossh
来使这个隧道可以自动重连# 暴露本地ssh端口到远端服务器端口
ssh-to-expose-ssh-server:
image: jnovack/autossh
container_name: autossh-ssh-to-expose-ssh-server
# 使用宿主机的网络
network_mode: host
environment:
- SSH_HOSTUSER=root
- SSH_HOSTNAME=123.123.123.123
- SSH_HOSTPORT=23
- SSH_TUNNEL_REMOTE=9999
- SSH_TUNNEL_HOST=127.0.0.1
- SSH_TUNNEL_LOCAL=22
restart: always
volumes:
- ~/.ssh/id_rsa:/id_rsa这样在【跳板机J】上就可以通过
ssh -p 9999 root@127.0.0.1
远程连接到【公司主机A】了- 【跳板机J】设置动态转发作为代理服务器, 将接收到的请求再转发到【公司主机A】, 在【跳板机J】上按照下面的命令配置:
ssh -p 9999 -Nf -D 0.0.0.0:1080 root@127.0.0.1
同样的,要把【跳板机J】的公钥复制到【公司主机A】上实现免密登录
# 创建ssh密钥对
ssh-keygen -t rsa -b 4096 -C "备注2"
# 追加本机公钥到远程服务器
cat ~/.ssh/id_rsa.pub | ssh -p 9999 root@127.0.0.1 "cat - >> ~/.ssh/authorized_keys"当然也可以使用
docker
启动autossh
:# 使用 SSH TUNNEL 创建 SOCKS5 代理
ssh-tunnel-socks5-server:
image: jnovack/autossh
container_name: ssh-tunnel-socks5-server
entrypoint:
autossh
-M 0
-N
-o ServerAliveInterval=5
-o ServerAliveCountMax=1
-o "ExitOnForwardFailure yes"
-o "StrictHostKeyChecking no"
-t -t
-i /id_rsa
-D 0.0.0.0:1080
-p 9999
# 使用宿主机的IP
root@172.17.0.1
ports:
- "1081:1080"
restart: always
volumes:
- ~/.ssh/id_rsa:/id_rsa这样【家里主机F】就可以通过设置代理【跳板机J】连接上阿里云上的服务器了。原理:【公司主机A】和【跳板机J】联合组成代理层。调用链路为:【家里主机F】 -- 使用代理 --> 【跳板机J】 -- ssh 隧道 --> 【公司主机A】 -- 转发 --> 阿里云服务器。(注:组成代理层还有另一种方式:【公司主机A】开代理服务同时把端口远程暴露到【跳板机J】上, 通过这种方式就可以配置代理服务的密码了, 具体配置参照这里)
- 将【公司主机A】的端口【22】映射到【跳板机J】的端口【9999】上, 在【公司主机A】按照下面的命令配置(【跳板机J】需要按上文方式将
就这么两步配置已经打通"公司网络"和"家里网络"了。不过,貌似实现的效果是单向的诶(只能家里连公司,公司还不能连家里, 如下图),【家里主机F】按【公司主机A】的步骤再配一下就好啦。
拓展
-
使用代理访问受限制的网站(比如公司内网的项目):
- 由于代理服务器使用的
SOCKS5
协议,Chrome
上安装SwitchyOmega
插件配置代理服务器地址,即可通过代理服务器访问受限制的服务了。 - 将
SOCKS5
协议转为HTTP
协议,然后通过系统自带的方式(Win下设置IE的Internet属性
,移动设备设置WIFI 的 HTTP 代理
)来设置全局代理,docker-compose
配置如下:
# 使用gost代理 SOCKS5 端口
gost-server:
image: ginuerzh/gost
command: -L=:8080 -F=socks5://ssh-to-local-proxy:1080
ports:
- "1082:8080"
restart: always # 使用privoxy代理 SOCKS5 端口
privoxy:
image: rdsubhas/tor-privoxy-alpine
entrypoint: sh -c 'echo "listen-address 0.0.0.0:8118" > /etc/service/privoxy/config && echo "forward-socks5 / ssh-to-local-proxy:1080 ." >> /etc/service/privoxy/config && privoxy --no-daemon /etc/service/privoxy/config'
ports:
- "1083:8118"
restart: always这里给出两种转换方式:
gost
和privoxy
, 选择其中一种方式即可。privoxy
找不到纯净的镜像, 都是捆绑tor
的, 就挑一个最精简的来做修改吧。- 其实还可以在【公司主机A】搭建
SS 服务器
, 然后就可以通过SS 客户端
来连接代理。具体的本文就不细说了,搭建示例可以看这里对应的 compose 文件
- 由于代理服务器使用的
终端工具中使用代理来连接阿里云服务器
这里的例子使用WinSCP
, 其他工具应该也差不多:新建站点->编辑->高级->连接
- ssh隧道方式:使用【跳板机J】的【9999】端口加【公司主机A】的帐号、密码、端口。
- 代理方式:可以选择
SOCKS5
协议或者HTTP
协议,和上面的配置一致即可。
其他问题
- SSH连接可能会中断(临时的网络拥塞、SSH 超时、中继主机重启等等),所以可以借助
autossh
实现自动重连来保证可靠的服务 - SSH连接有超时断开的机制,
WinSCP
有时经常会提示断开重连,有两种方式来维持连接:- 设置->面板->远程->修改刷新面板间隔为30s或者更短
- session设置->高级->连接->keepalives->执行哑命令(空SSH包是没效果的)
-
Win10 1803
已经默认集成了SSH 工具
,可以直接使用上面的命令。当然也可以借助终端工具来建立SSH隧道,比如在MobaXterm
上可以使用图形界面进行设置,比较直观。 - 文中的方法使用两级代理三次转发(如果在docker中运行那就是四次转发)实现不同网络的访问,中间代理层的带宽就限制了整体的访问速度,需要注意下
- 跳板机提供的
SOCKS5
代理服务没有密码,如果被别人知道了 IP 和端口容易被恶意攻击,所以一定要做好安全措施(比如:安全组或防火墙限制跳板机的入网 IP 为自己指定的 IP) - 你公司其他同事也想连你家里的电脑?总不能把【跳板机】暴露给他吧,太不安全了,你本地再开一层代理,让他用你的电脑作为代理好了。
仓库
基于 docker-compose
运行的完整配置已经上传至GitHub
参考文章
- SSH隧道技术----端口转发,socket代理
- 通过 SSH 实现 TCP / IP 隧道(端口转发):使用 OpenSSH 可能的 8 种场景
- winScp如何通过隧道代理进行远程连接
- ssh tunnel 三种模式
- SSH Tunnel | SSH.COM
- SSH port forwarding - Example, command, server config | SSH.COM
吐槽
发布文章还会莫名其妙被锁定,也是醉了。好像是出现SS服务的全称就会被封,要了解更多相关内容的自己去 GitHub
用搜索 SS/SS-windows
( SS 替换为全称)。