ssh 通过跳板机登陆远程服务器
开心一刻
“老师,你认识元芳吗?”
“不”
“你认识程祖吗?”
“不”
“那你知道他们的姐是谁吗?”
“不”
“老师你都不知道,我怎么知道:原方程组的解是______?”
“……”
写在前面
公司服务器只能用内网访问,想要登陆内网服务器只能先登陆跳板机,然后在跳板机登陆内网服务器。不过总想能省点事,从本地直接登陆内网服务器,从网上找到通过 ssh 借助跳板机登陆的文章,自己尝试了之后觉得非常香,就在自己的播客中记录一下,其实就是懒,哈哈哈哈哈。
ProxyCommand
借助 ssh 的 -o 选项指定一条 ProxyCommand 命令,ProxyCommand 内部就是登陆跳板机的ssh命令,
命令格式如下:
ssh username@目标机器IP -p 22 -o ProxyCommand='ssh username@跳板机IP -W %h:%p'
或者
ssh username@目标机器IP -p 22 -o ProxyCommand='ssh username@跳板机IP nc -q 1 -w 30 %h %p'
说明:
ProxyCommand 后面跟随的命令放在那个位置不重要,和 -o 选项一起出现即可,后面跟的是一个完整的 ssh 命令;
第二种格式使用登陆跳板机后又使用 nc 命令连接,属于 ssh 登陆远程服务器之后执行一条命令的用法,效果与第一种一样
有时候登陆跳板机需要输入令牌密码,第一种命令可能就不如第二种命令了
命令实际使用起来会比较长,因此 ssh 提供了一个配置文件,可以将相关配置内容放到 ~/.ssh/config 中,例如:
Host 目标机器ip
# 调试容器登录配置
Port 22
ProxyCommand ssh -o "ControlMaster=no" 跳板机IP nc -q 1 -w 30 %h %p
配置好后,就可以使用 ssh username@目标机器IP 进行登陆。
上述配置便能登陆目标服务器,并处于目标用户的家目录下,而我在使用时需要进行特定的项目目录并且要导入一些环境变量,因此对于配置文件做了一些修改,以便我登陆服务器后就不必再导入相关的环境变量了,当然进入服务器之后手动导入环境变量也是可以的。
Host 目标机器ip
# 调试容器登录配置
Port 22
RequestTTY yes
ProxyCommand ssh -o "ControlMaster=no" 跳板机IP nc -q 1 -w 30 %h %p
RemoteCommand cd xxx ; bash --login
上述配置中 RemoteCommand 是为了进行服务器后先执行某些命令,加入 bash --login 不仅是为了导入 /etc/profile 下的环境变量,同时也能停留在目标服务器中,没加 bash --login 将只会执行 cd 命令,然后退出。这里加入了 RequestTTY yes 是分配一个服务器终端,否则会报 mesg: ttyname failed: Inappropriate ioctl for device 的错误,如果不加 bash --login,那么 RequestTTY yes 应该也可以不加。
上述配置也可以写成一条命令来执行,只不过会较长。
ProxyJump
需要 OpenSSH 7.3 以上版本才可以使用 ProxyJump, 使用下列命令查看OpenSSH 版本:
ssh -V
ProxyJump 命令行使用方法:
ssh -J username@domain:port username@目标服务器IP -p 22
可以直接使用上述命令通过跳板机直接登录内网机器,port 和 username 等选项可以不填,可根据需要进行填写。
如果需要通过多个跳板机则以 , 分割:
ssh username@目标机器IP -p 22 -J username1@跳板机IP1:22,username2@跳板机IP2:22
如果觉得每次都需要加上 -J 的配置很多麻烦,可以写到配置文件里。修改配置文件 ~/.ssh/config,默认没有需要自己创建。增加以下内容:
Host tiaoban1 # 代表跳板机 1
HostName 跳板机 1 的 IP
Port 22 # ssh 连接端口
User username1 # 跳板机 1 的用户名
Host tiaoban2 # 代表跳板机 2
HostName 跳板机 2 的 IP
Port 22 # ssh 连接端口
User username2 # 跳板机 2 的用户名
Host 目标机器ip
# 调试容器登录配置
Port 22
ProxyJump tianban1,tiaoban2
ProxyJump 实现的效果和 ProxyCommand 实现的效果是一样的,不过 ProxyJump 使用起来要比 ProxyCommand 简单许多,尤其是在用多个跳板机进行跳转时,ProxyCommand 就会变得比较复杂。但是我目前还没有使用到多个跳板机,因此 ProxyJump 还没有尝试使用,不过先把使用方法贴在这里,以便后面使用是查看。
ProxyJump 在使用之后其实也会转换成ProxyCommand 命令,大概会转换成Setting implicit ProxyCommand from ProxyJump: ssh -v -W '[%h]:%p' tiaoban1
,所以说 ProxyJump 只是简化了 ProxyCommand 命令。可以在执行ssh 命令时加上-v 选项查看。
其他有用的命令
1. 借助跳板机上传代码文件
scp -o "ProxyCommand ssh -p 22 root@10.182.34.52 nc -w 1 %h %p" -P 22 -r root@target.machine:/root/ .
如果 ~/.ssh/config 已有相关配置,则可以使用
scp root@target.machine:/root/ .
或者使用 rsync 上传文件
rsync -av -e 'ssh -o RemoteCommand=none' --delete-after ~/project_path/ root@10.152.34.233:/root --exclude=.git 2> /dev/null
- 借助跳板机执行远程服务器中的命令
ssh -o "ProxyCommand ssh -o \"ControlMaster=no\" gwpek. nc -q 1 -w 30 %h %p" -p 22 "root@${addr}" -o 'RemoteCommand pwd' &> /dev/null
这里执行远程服务器中的命令借助了 RemoteCommand ,不过这里执行完后就会退出,并不会停留在远程服务起中,其中远程服务器命令执行之后的结果可以直接打印到本地。
这里的命令有时候也可以这样写:
ssh -o "ProxyCommand ssh -o \"ControlMaster=no\" gwpek. nc -q 1 -w 30 %h %p" -p 22 "root@${addr}" 'pwd' &> /dev/null
ssh 执行远程服务器命令可以直接在最后把想要执行的命令写上去,但是我自己尝试了之后有时候在 terminal 中无法执行,但是放到脚本里执行没问题,具体原因也没定位出来。但是 RemoteCommand 是可以的,不管是直接执行还是放到脚本里执行。我估计 RemoteCommand 就是为了替换直接写命令的那种方式而加入的。
总结
还是熟能生巧,要多踩些坑,才能更快解决碰到的问题。