原创:打码日记(微信公众号 ID:codelogs),欢送分享,转载请保留出处。
场景
很多时候,咱们须要批量操作多台机器,业界个别应用 Ansible 来实现,但应用 Ansible 来操作多台机器的前提是须要有 ssh 权限的,可悲的是,对于开发人员来说,个别是没有正式环境机器的 ssh 权限的,只能通过一个指定的入口登录机器,也能够了解,毕竟正式环境如此重要。
不过,如果你的生产环境能够拜访你的开发机,那么能够通过反向 Shell 来拜访机器,而后将反向 Shell 与 tmux 联合,又可实现同时操作多台机器的成果,这就是本文要介绍的。
正反向 Shell
如果你理解过 nc 命令,肯定据说过 nc 能够建设正向或反向 Shell,这里就不解释正向或反向 Shell 的概念了,解释不清,间接上 nc 实现正向 Shell 与反向 Shell 的例子。
因为 nc 命令自身存在模糊性,有些文章介绍的 nc 命令是 ncat,有些文章介绍的 nc 命令又是 netcat,这两个还是有些差异的,故这里的例子,间接应用 ncat 防止混同。
开发机 ip 为 192.168.0.10
服务器 ip 为 192.168.0.1
# 正向 Shell,1. 服务器上应用 ncat 监听
ncat -l 9999 -e /bin/bash
#正向 Shell,2. 开发机上连贯
ncat 192.168.0.1 9999
#反向 Shell,1. 开发机上应用 ncat 监听
ncat -l 9999
#反向 Shell,2. 服务器上连贯
ncat 192.168.0.10 9999 -e /bin/bash
成果如下:
- 正向 Shell:ncat 在服务器上以 9999 端口监听,当开发机用 ncat 连贯,连贯胜利后,服务器上的 ncat 会关上一个 bash 过程为这个连贯服务。
- 反向 Shell:ncat 在开发机上以 9999 端口监听,当服务器用 ncat 连贯,连贯胜利后,服务器上的 ncat 会关上一个 bash 过程为这个连贯服务。
其实正反向 Shell 的区别只是建设 TCP 连贯的方向不同而已,如下为 ncat 提供的 Shell 大略交互过程:ncat(client) <-> ncat(server) <-> bash
当在开发机的 ncat 外面输出命令并 Enter 后,命令会通过 ncat(client)走网络,发送给 ncat(server),ncat(server)收到命令后,会将命令发送给 bash 过程执行,bash 过程执行后,命令执行的后果,又会返回给 ncat(server),而 ncat(server)又通过网络连接返回给开发机上的 ncat(client)显示进去。
然而,当你真正来应用这个反向 Shell 时,会发现有诸多不便,比方应用 tail - f 来查看日志文件,完预先你想 Ctrl + C 退出 tail,却发现连 ncat 过程也退出了,这是最无法忍受的一点了,另外,像 Tab 补全
/Up Arrow history
/vim
/Ctrl + d
/Ctrl + z
之类的,也都无奈应用,十分好受。咱们个别称获取到的这种 Shell 叫 Weak Shell,而如果要获取 Strong Shell,就须要 socat 上场了。
通过 socat 获取 Strong Shell
socat 与 nc 命令相似,但它比 nc 要弱小得多,比方通过 socat 能够获取一个残缺的 Shell,如下:
# 正向 Shell,1. 服务器上应用 socat 监听
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp-listen:9999,bind=0.0.0.0,reuseaddr,fork
#正向 Shell,2. 开发机上连贯
socat file:`tty`,raw,echo=0 tcp:192.168.0.1:9999
#反向 Shell,1. 开发机上应用 socat 监听
socat file:`tty`,raw,echo=0 tcp-listen:9999,bind=0.0.0.0,reuseaddr,fork
#反向 Shell,2. 服务器上连贯
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.0.10:9999
成果如下:
原理和 ncat 相似,不过 socat 能够提供 tty 和 pty,因为像 Ctrl + C 之类的,自身就是终端 tty 提供给 bash 的信号,而不是字符,所以在 ncat 里,因为没有 tty,Ctrl + C 信号是无奈传递给服务端的 bash 程序的。
socat 提供的 Shell 交互过程大略是这样的:tty <-> socat(client) <-> socat(server) <-> pty <-> bash
那什么是 tty?这里我也了解得不是很透彻,能够简略认为键盘和屏幕就是 tty,键盘敲的内容会作为 tty 的输出,tty 输入的内容,会显示到屏幕上。
tmux 实现多机同时操作
tmux 是一个终端复用器,最罕用的是实现分屏,既然通过 socat 曾经能够获取到反向 Shell 了,那么把各个机器的反向 Shell 显示到 tmux 的各个分屏上,就能够看到多个反向 Shell 的命令执行后果,同时,将某个非凡分屏的 tty 操作,同时转发给多个反向 Shell,就实现了多机同时操作,成果如下:
上面是实现多机操作的命令:
# 1. 开发机上监听
nohup socat tcp-listen:9999,bind=0.0.0.0,reuseaddr,fork exec:'bash socatscript.sh' &
# 2. 在多个服务器上连贯
nohup socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:192.168.0.10:9999 &
# 3. 进入 tmux 分屏界面
tmux a -t socatSession
这是脚本 socatscript.sh 的实现
#!/bin/bash
SOCKDIR=$(mktemp -d)
SOCKF=${SOCKDIR}/usock
SESSION_NAME=${1:-socatSession}
WINDOW_NAME=${2:-socatWindown}
# create session and window
tmux has-session -t $SESSION_NAME
if [[$? -eq 1]];then
tmux new -s $SESSION_NAME -n $WINDOW_NAME -d "socat file:\`tty\`,raw,echo=0 exec:'ncat -lk 9998'"
fi
# split windown 0
tmux split-window -h -t 0 "socat file:\`tty\`,raw,echo=0 UNIX-LISTEN:${SOCKF},umask=0077"
tmux select-pane -t 0
tmux select-layout -t $WINDOW_NAME main-horizontal
tmux resize-pane -t 0 -y 2
# Wait for socket
while test ! -e ${SOCKF} ; do sleep 1 ; done
while ! $(ncat -z localhost 9998) ;do sleep 1; done;
# Use socat to ship data between the unix socket and STDIO.
socat -U STDOUT TCP:localhost:9998 &
exec socat STDIO UNIX-CONNECT:${SOCKF}
次要性能是,每当有一个反向 Shell 连贯时,在 tmux 上新建一个分屏,并将反向 Shell 显示在这个新建的分屏上,同时,提供一个非凡的分屏 (最下面那个),在这个分屏上的输出的命令,会转发到各个反向 Shell 里。
如果你发现反向 Shell 里的文字不能满屏显示,须要通过 stty rows 63 columns 204
从新设置一下以后 tty 的显示宽高。
并且,如果你有 ssh 机器的权限,同时也想应用这种 tmux 分屏的形式执行命令,只须要将 bash 更换成 ssh 即可,如下:
# 1. 开发机上监听
nohup socat tcp-listen:9999,bind=0.0.0.0,reuseaddr,fork exec:'bash socatscript.sh' &
# 2. 开发机上,应用 ssh 连贯到多个机器
nohup socat exec:'sshpass -p"xxx"ssh root@192.168.0.10',pty,stderr,setsid,sigint,sane tcp:localhost:9999 &
# 3. 进入 tmux 分屏界面
tmux a -t socatSession
是不是很爽,连 ansible 也能够不必装了!
总结
socat 命令十分的弱小,值得好好的钻研一翻,同时当你钻研胜利后,会发现自己对各种概念的了解,又回升了一步。