We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
平时经常遇到下面的情况:
一般情况下的对应方法:
本文的目的就是使用 SSH TUNNEL 这项技术解决上面的问题,也就是打通所谓的 公司网络 和 家里网络 。
经常远程连接 Linux 服务器的小伙伴,对于 ssh 这个命令应该不陌生吧。它还可以不执行远程指令只建立一条和远程服务器之间的连接,也就是形成了一条通道,在这条通道上我们就可以做一些文章了。 先看下 ssh 命令的参数介绍( 需要了解更多请通过命令 man 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 )
-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 [email protected] 说明: 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 [email protected] 说明: 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 [email protected] 说明: 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 [email protected] "cat - >> ~/.ssh/authorized_keys" # 或者直接复制本机公钥到远程服务器( 会覆盖掉远程服务器已有的其他公钥 ) $ scp -P 23 -p ~/.ssh/id_rsa.pub [email protected]:~/.ssh/authorized_keys
步骤:
将 公司主机 A 的端口 22 映射到 跳板机 J 的端口 9999 上,在 公司主机 A 按照下面的命令配置( 跳板机 J 需要按上文中的方式将 GatewayPorts 设为 true )
true
$ ssh -p 23 -Nf -R 9999:127.0.0.1:22 [email protected]
当然也可以通过 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 [email protected] 远程连接到 公司主机 A 了
ssh -p 9999 [email protected]
在 跳板机 J 上设置动态转发使其作为 代理服务器 ,将接收到的请求再转发到 公司主机 A
在 跳板机 J上执行下面的命令
$ ssh -p 9999 -Nf -D 0.0.0.0:1080 [email protected]
同样的,要把 跳板机 J 的 公钥 复制到 公司主机 A 上实现免密登录
# 创建 ssh 密钥对 $ ssh-keygen -t rsa -b 4096 -C "备注2" # 追加本机公钥到远程服务器 $ cat ~/.ssh/id_rsa.pub | ssh -p 9999 [email protected] "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 [email protected] ports: - "1081:1080" restart: always volumes: - ~/.ssh/id_rsa:/id_rsa
这样 家里主机 F 就可以通过设置代理 跳板机 J 连接上 阿里云 上的服务器了。
原理: 公司主机 A 和 跳板机 J 联合组成 代理层 。调用链路为: 家里主机 F -- 使用代理 --> 跳板机 J -- ssh 隧道 --> 公司主机 A -- 转发 --> 阿里云 服务器。
注 :组成 代理层 还有另一种方式: 公司主机 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 协议,和上面的配置一致即可。
MobaXterm
基于 docker-compose 运行的完整配置已经上传至 GitHub 。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
平时经常遇到下面的情况:
一般情况下的对应方法:
本文的目的就是使用 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
)本地转发
本地监听指定端口,该端口收到的请求会通过远程服务器转发到另一台机器的指定端口上
语法:
示例:
上面示例中相当于将远程主机 123.123.123.124 的 3001 端口映射为本地的 3000 端口,这样就可以通过局域网访问被限制的公网服务了。
远程转发
远程服务器上监听指定端口,该端口收到的请求会通过本地转发到另一台机器的指定端口上
语法:
示例:
上面示例中相当于将局域网主机 192.168.1.100 的 3001 端口映射为远程服务器 123.123.123.123 的 3000 端口,这样就可以通过公网来访问局域网中的服务了。
动态转发
监听本地的指定端口,本机将作为 SOCKS5 服务器使用
语法:
示例:
上面示例中相当于开启了一个 代理服务器 ,比起 本地转发 需要指定具体端口来说更加方便。
正文
上面已经介绍了 SSH TUNNEL 的使用方式,接下来就开始干正事了,先上两张网络拓扑图。
对比两张图把少的线连上就好了,是不是很 easy ?
原先环境:
三个独立的网络: 公司内网 、 家里内网 、 阿里云专有网络 ,其中可以通过 公司网络 访问 阿里云 上的服务器而 家里网络 则不行。
目标:
预备工作:
有一台公网的服务器作为 跳板机 ,公司和家里都能访问到它
( 没有服务器?阿里云腾讯云学生机弄台玩玩 )
因为 ssh 命令不能添加密码作为参数,只能手动输入,而且每次连接都要重新输入也不是很方便,这里采用 公钥方式 登录就可以免输密码了
步骤:
将 公司主机 A 的端口 22 映射到 跳板机 J 的端口 9999 上,在 公司主机 A 按照下面的命令配置( 跳板机 J 需要按上文中的方式将 GatewayPorts 设为
true
)当然也可以通过 docker 运行 autossh 来使这个隧道可以自动重连
这样在 跳板机 J 上就可以通过
ssh -p 9999 [email protected]
远程连接到 公司主机 A 了在 跳板机 J 上设置动态转发使其作为 代理服务器 ,将接收到的请求再转发到 公司主机 A
在 跳板机 J上执行下面的命令
同样的,要把 跳板机 J 的 公钥 复制到 公司主机 A 上实现免密登录
当然也可以使用 docker 启动 autossh
这样 家里主机 F 就可以通过设置代理 跳板机 J 连接上 阿里云 上的服务器了。
原理: 公司主机 A 和 跳板机 J 联合组成 代理层 。调用链路为: 家里主机 F -- 使用代理 --> 跳板机 J -- ssh 隧道 --> 公司主机 A -- 转发 --> 阿里云 服务器。
注 :组成 代理层 还有另一种方式: 公司主机 A 开代理服务同时把端口远程暴露到 跳板机 J 上,通过这种方式就可以配置代理服务的密码了,具体配置参照 这里 。
就这么两步配置已经打通公司网络和家里网络了。不过,貌似实现的效果是单向的诶( 只能家里连公司,公司还不能连家里,如下图所示 )
解决办法: 家里主机 F 按 公司主机 A 的步骤再配一遍就好啦。
拓展
使用代理访问受限制的网站( 比如公司内网的项目 ):
由于代理服务器使用的是 SOCKS5 协议, Chrome 上安装 SwitchyOmega 插件配置代理服务器地址,即可通过代理服务器访问受限制的服务了。
将 SOCKS5 协议转为 HTTP 协议,然后通过系统自带的方式( Win 下设置 IE 的 Internet 属性 ,移动设备设置 WIFI 的 HTTP 代理 )来设置全局代理, docker-compose 配置如下:
这里给出两种转换方式: gost 和 privoxy ,选择其中一种方式即可。 privoxy 找不到纯净的镜像,都是捆绑 tor 的,就挑一个最精简的来做修改吧。
其实还可以在 公司主机 A 搭建 SS 服务器 ,然后就可以通过 SS 客户端 来连接代理。具体的本文就不细说了,搭建示例可以看 这里 对应的 compose 文件。
终端工具中使用代理来连接云服务器
这里的例子使用 WinSCP ,其他工具应该也差不多:新建站点 -> 编辑 -> 高级 -> 连接
ssh 隧道方式 :使用 跳板机 J 的 9999 端口加 公司主机 A 的帐号、密码、端口。
代理方式 :可以选择 SOCKS5 协议或者 HTTP 协议,和上面的配置一致即可。
其他问题
MobaXterm
上可以使用图形界面进行设置,比较直观。仓库
基于 docker-compose 运行的完整配置已经上传至 GitHub 。
参考文章
转载请注明出处: https://www.jianshu.com/p/388a93b1e7f7
The text was updated successfully, but these errors were encountered: