Posted on 2021-02-18 19:02
魔のkyo 阅读(710)
评论(0) 编辑 收藏 引用 所属分类:
Linux
SSH Tunnel解决的问题是让原本不能访问的端口(通常是因为在不同局域网)可以访问。
假设A要访问D:6379,A、D在不同局域网,最简单方法是在D所在的局域网网关上配置端口映射把D:6379映射到公网,但是很多时候出于某些因素(例如:安全考量、没有配置网关的权限、服务本身配置了只允许本地访问),不希望或无法通过把D:6379映射到公网解决,就可以考虑使用SSH Tunnel。
情形1:D所在的局域网有主机C的22端口是被映射到公网的,不妨假设映射成了X:30022,X是C和D所在局域网网关在公网的IP地址,那么可以在主机A上通过命令
HostA$ ssh -L 36379:D:6379 root@X -p 30022
把D:6379映射成了A:36379,特别情况C和D是同一台主机,D可以写成localhost。
情形2:A所在的局域网有主机B的22端口是被映射到公网的,不妨假设映射成了X:30022,X是A和B所在局域网网关在公网的IP地址,那么可以在主机D上通过命令
HostD$ ssh -g -R 36379:D:6379 root@X -p 30022
把D:6379映射成了B:36379,而A和B是同一局域网的,因此A可以访问到B:36379。
按理说上面的命令加了-g参数,B:36379应该被绑定在0.0.0.0:36379,但实际测试发现绑定在了127.0.0.1:36379,导致无法在A上访问,原因暂时未知(确定不是因为redis配置了保护模式),不过可以通过类似情形1的方式再把B:36379映射成A:36379,这样A就可以访问了。
HostA$ ssh -L 36379:localhost:36379 root@B
情形3:A和D所在局域网都没有主机的ssh端口被映射到公网,但我有另一台具有公网IP的主机,不妨假设为X开启着22端口,类似情形2通过命令
HostD$ ssh -R 36379:D:6379 root@X
HostA$ ssh -L 36379:localhost:36379 root@X
之后让A访问A:36379即可。
通过命令建立SSH Tunnel之后会登录到作为跳板的机器,通常我们是不需要使用这个控制台的,因此可以通过-f参数让ssh在后台运行,需要关闭tunnel时直接杀死进程。
其他常用选项:
f表示后台用户验证,这个选项很有用,没有shell的不可登陆账号也能使用.
例如情形1中的命令可以写成
ssh -CfNg -L 36379:D:6379 root@X -p 30022
通过
可以查看打开的tunnel。
当网络不稳定时,ssh tunnel会自动断开,如果是前台的运行方式,会自动退出远程控制台,回到本地控制台提示符,如果是后台运行方式,进程会自动结束,这时候可以使用autossh工具来帮助自动重连。
只需要把ssh命令中的ssh换成autossh -M <port>
例如情形1中的命令可以写成
autossh -M 46379 -CfNg -L 36379:D:6379 root@X -p 30022
-M 后面的端口号是用来监视连接状态的,允许指定为0,这里指定为0是否可以正常监视重连以及如何监视有待研究。
另外autossh不支持输入密码,可以配合expect脚本自动输入密码或者通过密钥登录,更推荐使用密钥方式。
先在本地生成密钥
会询问将密钥放在何处,默认即可。然后是输入密码,留空(否则你登录不仅需要私钥还要输入密码)。
完成后在~/.ssh目录下会生成另个文件id_rsa和id_rsa.pub,一个私钥一个公钥。
然后将公钥写入远程用户家目录下的~/.ssh/authorized_keys文件中,通过ssh-copy-id命令可以帮我们实现这一操作(相当于把公钥复制过去再追加到authorized_keys的尾部)
ssh-copy-id [-p SSH端口默认22] [user@]hostname
参考: