[Linux] Dockerコンテナ同士で仮想シリアルポートをつないでみる。を詳しく

2018年9月18日火曜日

Docker linux socat

Dockerコンテナ同士で仮想シリアルポートをつないでみる。では、socatを使って2つのコンテナ同士をつないだ。
どのようにつながっているのかを順を追って見てみよう。

Server1でlisten

まずは前回同様にServer1側を起動する。
socat実行時に -d -d オプションをつけて、詳細なメッセージを見てみる。

# socat -d -d tcp-l:1234,reuseaddr pty,raw,echo=0,link=/dev/ptty0 &
# 2018/08/24 23:29:10 socat[12] N listening on AF=2 0.0.0.0:1234

1234ポートでlistenしているのがわかる。

Server2から接続

次にServer2側から接続してみる。この時も -d -d オプションをつけて、詳細なメッセージを見てみよう。

# socat -d -d pty,raw,echo=0,link=/dev/ptty0 tcp:server1:1234 &
# 2018/08/24 23:31:41 socat[12] N PTY is /dev/pts/2
2018/08/24 23:31:41 socat[12] N opening connection to AF=2 172.22.0.2:1234
2018/08/24 23:31:41 socat[12] N successfully connected from local address AF=2 172.22.0.3:50376
2018/08/24 23:31:41 socat[12] N starting data transfer loop with FDs [5,5] and [7,7]

Server2の50376ポートとserver1の1234ポートが接続されている。
最後の行からは、ファイルディスクリプタ5から7へのデータ転送をsocatがしていることが読み取れる。

この時、Server1側には以下のようなメッセージが表示される。

# 2018/08/24 23:31:41 socat[12] N accepting connection from AF=2 172.22.0.3:50376 on AF=2 172.22.0.2:1234
2018/08/24 23:31:41 socat[12] N PTY is /dev/pts/2
2018/08/24 23:31:41 socat[12] N starting data transfer loop with FDs [6,6] and [5,5]

こちらはファイルディスクリプタ6から5へのデータ転送をsocatがしていることがわかる。

では、ファイルディスクリプタの正体は

それぞれのファイルディスクリプタがどこを指しているのか見てみよう。
Server1を見てみる。

# ps | grep socat
   12 root      0:00 socat -d -d tcp-l:1234,reuseaddr pty,raw,echo=0,link=/dev/ptty0
# ls -l /proc/12/fd
total 0
lrwx------    1 root     root            64 Aug 24 23:39 0 -> /dev/pts/1
lrwx------    1 root     root            64 Aug 24 23:39 1 -> /dev/pts/1
lrwx------    1 root     root            64 Aug 24 23:39 2 -> /dev/pts/1
lrwx------    1 root     root            64 Aug 24 23:39 3 -> socket:[223319]
lrwx------    1 root     root            64 Aug 24 23:39 4 -> socket:[223320]
lrwx------    1 root     root            64 Aug 24 23:39 5 -> /dev/pts/ptmx
lrwx------    1 root     root            64 Aug 24 23:39 6 -> socket:[223333]
lrwx------    1 root     root            64 Aug 24 23:39 7 -> /dev/pts/2

Server1では6から5へsocatがデータを転送していた。

FD6を見てみる。
6 -> socket:[223333]
ここで、223333はinode番号で、inode番号とソケットの情報を突き合わせるには /proc/net/tcp を見る。

# cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 0B00007F:AFF5 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 223059 1 0000000000000000 100 0 0 10 0                    
   1: 020016AC:04D2 030016AC:C4C8 01 00000000:00000000 00:00000000 00000000     0        0 223333 1 0000000000000000 21 0 0 10 -1   
# printf "%d\n" 0x04D2
1234

FD5を見てみる。
5 -> /dev/pts/ptmx

ptmxというのは擬似端末のマスター側でsocatが読み書きしている方。

https://linuxjm.osdn.jp/html/LDP_man-pages/man4/pts.4.html

# ls -l /dev/ptty0 
lrwxrwxrwx    1 root     root            10 Aug 24 23:31 /dev/ptty0 -> /dev/pts/2

結局、/dev/ptty0に書き込むと、以下のようにデータが流れていくってことだね。

/dev/ptty0(/dev/pts/2) ->[擬似端末]->
/dev/pts/ptmx ->[socat]->
socket:172.22.0.2:1234