labunix's blog

labunixのラボUnix

(gns3)IOS/IOUのコンソール接続用の待受ポートをsocatで中継する。

(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]11で対応している。

$ 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 
#show run | section line vty 0 4
line vty 0 4
 password cisco
 login
 transport input telnet
#show run | inc ena             
enable password cisco
#show run | section Vlan
interface Vlan1
 ip address 192.168.0.12 255.255.255.0
 shutdown
#show run | section 0/0 
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