1. 程式人生 > 其它 >使用socat反向Shell多臺機器

使用socat反向Shell多臺機器

原創:打碼日記(微信公眾號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 [email protected]',pty,stderr,setsid,sigint,sane tcp:localhost:9999 &
# 3.進入tmux分屏介面
tmux a -t socatSession

是不是很爽,連ansible也可以不用裝了!

總結

socat命令非常的強大,值得好好的研究一翻,同時當你研究成功後,會發現自己對各種概念的理解,又上升了一步。