■(gns3)IOS/IOUのコンソール接続用の待受ポートをsocatで中継する。
telnet接続のためには、ログイン、enable password設定が必要になる。
gns3を稼働させているホストにsshログインしてgns3が用意する
NW機器のコンソール接続につなげる方が安全。
今回はgns3が用意する各NW機器のコンソールの127.0.0.1:XXXXのポートを
socatで内部の別ホストのために公開する方法について調べてみた。
$ lsb_release -d
Description: Debian GNU/Linux 9.5 (stretch)
$ dpkg -l | awk '/^ii/&&/gns3/{print $2,$3}'
gns3-gui 2.1.11~xenial1
gns3-server 2.1.11~xenial1
■IOS/IOUのコンソール接続用の待受ポートを確認。
gns3でIOS/IOUを起動すると、gns3serverのpidが新たにfd(socket)をオープンして127.0.0.1:50xx]から順に待ち受ける。
TCPで待ち受けてるfdはsocketであることが/proc/[pid]/fd/[num]で確認出来る。
fd/[num]は/proc/net/tcp内でsocketのinodeとして、16進数の[ip address]:[port num]と1対1で対応している。
$ ss -tlnp | awk '/127.0.0.1:[0-9]/&&/gns3server/{print $4,$NF}'
127.0.0.1:3080 users:(("gns3server",pid=21871,fd=8))
127.0.0.1:5014 users:(("gns3server",pid=21871,fd=49))
127.0.0.1:5015 users:(("gns3server",pid=21871,fd=54))
127.0.0.1:5016 users:(("gns3server",pid=21871,fd=21))
127.0.0.1:5017 users:(("gns3server",pid=21871,fd=61))
127.0.0.1:5018 users:(("gns3server",pid=21871,fd=40))
127.0.0.1:5019 users:(("gns3server",pid=21871,fd=33))
127.0.0.1:5020 users:(("gns3server",pid=21871,fd=31))
127.0.0.1:5021 users:(("gns3server",pid=21871,fd=60))
127.0.0.1:5022 users:(("gns3server",pid=21871,fd=66))
127.0.0.1:5023 users:(("gns3server",pid=21871,fd=30))
127.0.0.1:5024 users:(("gns3server",pid=21871,fd=39))
127.0.0.1:5025 users:(("gns3server",pid=21871,fd=25))
$ ss -tlnp | awk -F, '/127.0.0.1:[0-9]/&&/gns3server/{gsub("[a-z]*=|)","",$0);print "ls -l /proc/"$(NF-1)"/fd/"$NF}' \
| sh | awk '{print $(NF-2),"->",$NF}'
/proc/21871/fd/8 -> socket:[3203213]
/proc/21871/fd/49 -> socket:[3227358]
/proc/21871/fd/54 -> socket:[3227359]
/proc/21871/fd/21 -> socket:[3228559]
/proc/21871/fd/61 -> socket:[3233796]
/proc/21871/fd/40 -> socket:[3223388]
/proc/21871/fd/33 -> socket:[3223383]
/proc/21871/fd/31 -> socket:[3230954]
/proc/21871/fd/60 -> socket:[3225521]
/proc/21871/fd/66 -> socket:[3225522]
/proc/21871/fd/30 -> socket:[3223329]
/proc/21871/fd/39 -> socket:[3223382]
/proc/21871/fd/25 -> socket:[3223328]
$ ss -tlnp | awk -F, '/127.0.0.1:[0-9]/&&/gns3server/{gsub("[a-z]*=|)","",$0);print "ls -l /proc/"$(NF-1)"/fd/"$NF}' \
| sh | awk '{gsub(".*\\[|\\]","",$NF); \
print "awk \047$10 ~ /"$NF"/{gsub(\042.*:\042,\0420x\042,$2); \
printf \042%s\134n\042,tolower($2)}\047 /proc/net/tcp | xargs printf 127.0.0.1:\042%d\134n\042"}' | sh
127.0.0.1:3080
127.0.0.1:5014
127.0.0.1:5015
127.0.0.1:5016
127.0.0.1:5017
127.0.0.1:5018
127.0.0.1:5019
127.0.0.1:5020
127.0.0.1:5021
127.0.0.1:5022
127.0.0.1:5023
127.0.0.1:5024
127.0.0.1:5025
■socatでコンソールポートを中継する。
$ ss -tnlp | grep gns3server \
| awk '$4 !~ /3080/{gsub("127.0.0.1:","",$4); \
print "socat -d -lf "$4".log tcp-listen:"$4+3000",fork tcp-connect:127.0.0.1:"$4" &"}' | sh
$ ss -tnlp | grep :80[0-9]
LISTEN 0 5 *:8014 *:* users:(("socat",pid=12259,fd=5))
LISTEN 0 5 *:8015 *:* users:(("socat",pid=12260,fd=5))
LISTEN 0 5 *:8016 *:* users:(("socat",pid=12261,fd=5))
LISTEN 0 5 *:8017 *:* users:(("socat",pid=12262,fd=5))
LISTEN 0 5 *:8018 *:* users:(("socat",pid=12263,fd=5))
LISTEN 0 5 *:8019 *:* users:(("socat",pid=12264,fd=5))
LISTEN 0 5 *:8020 *:* users:(("socat",pid=12265,fd=5))
LISTEN 0 5 *:8021 *:* users:(("socat",pid=12266,fd=5))
LISTEN 0 5 *:8022 *:* users:(("socat",pid=12267,fd=5))
LISTEN 0 5 *:8023 *:* users:(("socat",pid=12268,fd=5))
LISTEN 0 5 *:8024 *:* users:(("socat",pid=12269,fd=5))
LISTEN 0 5 *:8025 *:* users:(("socat",pid=12270,fd=5))
■socatの中継を止める時は以下で。
$ ps aux | grep "soca[t]\|PID" | awk '($2 ~ /[0-9]/ && $NF ~ /50[0-9[0-9]/){print "kill "$2}' | sh
■lfで指定したログの出力は以下のように監視
$ tail -f 50[0-9][0-9].log
==> 5014.log <==
==> 5015.log <==
==> 5016.log <==
==> 5017.log <==
==> 5018.log <==
==> 5019.log <==
2018/11/04 23:52:27 socat[12785] N accepting connection from AF=2 192.168.0.5:48712 on AF=2 192.168.0.5:8019
2018/11/04 23:52:27 socat[12785] N forked off child process 12858
2018/11/04 23:52:27 socat[12785] N listening on AF=2 0.0.0.0:8019
2018/11/04 23:52:27 socat[12858] N opening connection to AF=2 127.0.0.1:5019
2018/11/04 23:52:27 socat[12858] N successfully connected from local address AF=2 127.0.0.1:35568
2018/11/04 23:52:27 socat[12858] N starting data transfer loop with FDs [7,7] and [6,6]
2018/11/05 00:02:19 socat[12858] N socket 1 (fd 7) is at EOF
2018/11/05 00:02:19 socat[12858] N socket 1 (fd 7) is at EOF
2018/11/05 00:02:19 socat[12858] N socket 2 (fd 6) is at EOF
2018/11/05 00:02:19 socat[12858] N exiting with status 0
2018/11/05 00:02:19 socat[12785] N childdied(): handling signal 17
==> 5020.log <==
==> 5021.log <==
==> 5022.log <==
==> 5023.log <==
==> 5024.log <==
==> 5025.log <==
■パケットキャプチャは以下で。
$ sudo tcpdump -tttt -s0 -w tel.pcap -i lo -n tcp dst portrange 8000-8099
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
■ホストとIOU_L2_151g_2を接続してtelnetの設定をする。
$ ip a show dev br1 | grep inet.*br1
inet 192.168.0.5/24 brd 192.168.0.255 scope global br1
$ telnet
line vty 0 4
password cisco
login
transport input telnet
enable password cisco
interface Vlan1
ip address 192.168.0.12 255.255.255.0
shutdown
interface Ethernet0/0
duplex auto
IOU_L2_151g_2#show ip interface brief | inc Vlan1
Vlan1 192.168.0.12 YES manual up up
$ telnet 192.168.0.12
Trying 192.168.0.12...
Connected to 192.168.0.12.
Escape character is '^]'.
User Access Verification
Password:
IOU_L2_151g_2>en
Password:
IOU_L2_151g_2#
■パケットキャプチャを確認。
srcポートが異なるのは別セッションとして接続されたことを表す。
$ sudo tcpdump -r tel.pcap -n 2>/dev/null | awk '/Flags/{a[$3" > "$5]+=1}END{for(n in a){print a[n],n}}'
65 192.168.0.5.49398 > 192.168.0.5.8019:
513 192.168.0.5.49952 > 192.168.0.5.8019:
69 192.168.0.5.49566 > 192.168.0.5.8019:
295 192.168.0.5.48712 > 192.168.0.5.8019:
■straceでコンソールの中身を覗く。
$ sudo strace -s 160 -p 21871 2>&1 | awk '/read/&&!/\(14/'
read(36, "\r\n*Nov 4 15:46:29.459: %CDP-4-DUPLEX_MISMATCH: duplex mismatch ", 262144) = 64
read(36, "discovered on Ethernet0/0 (not half duplex), with IOU_L2_151g_1 Ethernet0/0 (half", 262144) = 81
read(36, " duplex).", 262144) = 9
read(65, "\r\n*Nov 4 15:46:45.253: %CDP-4-DUPLEX_MISMATCH: duplex mismatch disc", 262144) = 68
read(65, "overed on Ethernet0/0 (not full duplex), with IOU_L2_15609s_2 Ethernet0/0 (full duplex).", 262144) = 88
read(38, "c", 262144) = 1
read(38, "o", 262144) = 1
read(38, "n", 262144) = 1
read(38, "f", 262144) = 1
read(38, " ", 262144) = 1
read(38, "t", 262144) = 1
read(38, "\r\nEnter configuration commands, one per line. End with CNTL/Z.", 262144) = 63
read(38, "\r\nIOU_L2_151g_2(config)#", 262144) = 24
read(38, "i", 262144) = 1
read(38, "n", 262144) = 1
read(38, "t", 262144) = 1
read(38, " ", 262144) = 1
read(38, "e", 262144) = 1
read(38, "0", 262144) = 1
read(38, "/", 262144) = 1
read(38, "0", 262144) = 1
read(38, "\r\n", 262144) = 2
read(38, "IOU_L2_151g_2(config-if)#", 262144) = 25
read(38, "d", 262144) = 1
read(38, "u", 262144) = 1
read(38, "\r\nIOU_L2_151g_2(config-if)#duplex ", 262144) = 34
read(42, "\r\n*Nov 4 15:47:05.233: %CDP-4-DUPLEX_MISMATCH: duplex mismatch ", 262144) = 64
read(42, "discovered on Ethernet0/0 (not half duplex), with IOU_L2_152d_2 Ethernet0/0 (half dup", 262144) = 85
read(42, "lex).", 262144) = 5
read(38, "f", 262144) = 1
read(38, "u", 262144) = 1
read(38, "\r\nIOU_L2_151g_2(config-if)#duplex full ", 262144) = 39
read(38, "\r\n", 262144) = 2
read(38, "IOU_L2_151g_2(config-if)#", 262144) = 25
read(38, "e", 262144) = 1
read(38, "n", 262144) = 1
read(38, "d", 262144) = 1
read(38, "\r\n", 262144) = 2
read(38, "IOU_L2_151g_2#", 262144) = 14
read(38, "w", 262144) = 1
read(38, "r", 262144) = 1
read(38, "i", 262144) = 1
read(38, "t", 262144) = 1
read(38, "e", 262144) = 1
read(38, "\r\nIOU_L2_151g_2#write ", 262144) = 22
read(38, "m", 262144) = 1
read(38, "e", 262144) = 1
read(38, "\r\nIOU_L2_151g_2#write memory ", 262144) = 29
read(38, "\r\n*Nov 4 15:47:08.782: %SYS-5-CONFIG_I: Configured from console by ", 262144) = 68
read(38, "console\r\nIOU_L2_151g_2#write memory ", 262144) = 36