[Linux] 建立 ssh tunnel 時,使用 expect 自動回答問題
之前 在 expect 程式中使用 if-else 判斷不同的登入狀況,
今天又遇上了需要使用 expect 的狀況,
雖然是相對簡單的情境,還是記錄一下~
因為公司網路的關係,要連到 Lab 需要透過一台跳板機,
因此我想要建立一個透過跳板機,連到 Lab 某機器的 ssh tunnel~
作法是 ssh 連上跳板機後,
看到 Password: 時,要先輸入帳號密碼。
接著要等待它出現一個 Duo two-factor login 以及 Passcode or option 的訊息,
再輸入 1 讓 Duo 把登入請求傳到我的手機 Duo app,
我在手機上接受之後,剛剛的 ssh tunnel 才會建立成功~
我先寫了一個 ssh_lab_tunnel.sh,
內容是呼叫 ssh_lab_tunnel_expect_duo.sh,
把建立 ssh tunnel 必要的參數傳進去
(這是簡化過的版本,不然就不需要多這一層了):
ssh_lab_tunnel_expect_duo.sh "31242:172.1.2.3:22" "domain\\[email protected]"
而 ssh_lab_tunnel_expect_duo.sh 是一個 expect 的 script,
它就是接收 ssh tunnel 需要的參數後,執行 ssh 命令,
先等待 “Password” 字串出現後,輸入密碼,
再等待 “Passcode or option” 字串出現後,輸入 1:
#!/usr/bin/expect set timeout 60 spawn ssh -NfL "*:[lindex $argv 0]" "[lindex $argv 1]" expect "Password" send "My password\n" expect "Passcode or option" send "1\n" expect "anything so that we will wait for ssh to respond after we click duo accept"
程式的最後,我讓它另外再等一個永遠等不到的字串,
因為如果沒那一行的話,expect 程式就會結束,
ssh 的 tunnel 就會在我還沒按下手機 app 接受鈕時,就中斷了~
反過來說,當 expect 在等那個等不到的字串時,
我可以按下手機 app 接受鈕,
這時 ssh 登入成功,tunnel 可以建立起來,
但因為有 -f 參數的關係,會使用一個背景程序來維持 tunnel,
剛剛執行的 ssh 命令則會結束。
可能是因為 ssh 命令結束的關係,expect 也就停止執行了,
不會繼續去等那個永遠等不到的字串~
(也不能 expect “” 空字串,這樣跟沒有等是一樣的)
來看看執行時的輸出吧~
可以看到 expect 自動輸入了密碼、選擇 1,
之後等 ssh tunnel 建立起來後,程式就結束:
spawn ssh -NfL *:31242:172.1.2.3:22 domain\[email protected] Password: Duo two-factor login for testuser Enter a passcode or select one of the following options: 1. Duo Push to +XXX XXX XXX 123 2. SMS passcodes to +XXX XXX XXX 123 Passcode or option (1-2): 1
expect 的語法對我來說,還是有點複雜,
幾乎每次要用時,都得去查一下,
因此還是多留一點記錄在網誌上囉~^^