poll: protocol failure in circuit setupの続き

以前の文章へのコメントで突っ込まれたので、rshで「poll: protocol failure in circuit setup」と言われるときにtcpdumpでログを取ってみた。

client)からserverにrshでpwdを実行するコマンドを投げている。

client# \rsh server pwd

tcpdumpの結果は、

IP client.1023 > server.shell: S 4253120909:4253120909(0) win 5840 <略>
IP server.shell > client.1023: S 1119539071:1119539071(0) ack 4253120910 win 5792 <略>
IP client.1023 > server.shell: . ack 1 win 1460 <略>
IP server.53908 > client.auth: S 1133396091:1133396091(0) win 5840 <略>
IP client > server: icmp 68: host client unreachable - admin prohibited
IP client.1023 > server.shell: P 1:6(5) ack 1 win 1460 <略>
IP server.shell > client.1023: . ack 6 win 1448 <略>
IP server.1023 > client.1022: S 1131978286:1131978286(0) win 5840 <略>
IP client > server: icmp 68: host client unreachable - admin prohibited
IP server.shell > client.1023: F 1:1(0) ack 6 win 1448 <略>
IP client.1023 > server.shell: . ack 2 win 1460 <略>
IP client.1023 > server.shell: F 6:6(0) ack 2 win 1460 <略>
IP server.shell > client.1023: . ack 7 win 1448 <略>
client:1023 → server:514(shell)にSYN
client:1023 ← server:514 SYN ACK
client:1023 → server:514 ACK

ここまででTCPの接続ができる。

server:53908 → client:113(auth)にSYN(接続しに行く)
server       ← client ICMP reject

この結果を受けてかどうか知らないが、メッセージを1つ投げると(たぶんポート番号を投げてます)、サーバが接続してきます。

client:1023 → server:514 メッセージ
client:1023 ← server:514 ACK
client:1022 ← server:1023 SYN(接続しに行く)
server      ← client ICMP reject

そして、

client:1023 ← server:514 FIN(接続を切る)
client:1023 → server:514 FIN ACK
client:1023 → server:514 FIN
client:1023 ← server:514 FIN ACK

というわけで、113番と1022番(ここでは)を空けなければいけないのはクライアント側です。

xinetd.dの認証が悪いのかということですが、xinetd.d/rshのlog_on_successとlog_on_failureをコメントアウトしても同様に「poll: protocol failure in circuit setup」が出ます。このときは以下のようにauthのSYN(最初にrejectされていたやつ)がなくなって、少し短かくなっていました。

IP client.1023 > server.shell: S 599020182:599020182(0) win 5840 <略>
IP server.shell > client.1023: S 1749509148:1749509148(0) ack 599020183 win 5792 <略>
IP client.1023 > server.shell: . ack 1 win 1460 <略>
IP client.1023 > server.shell: P 1:6(5) ack 1 win 1460 <略>
IP server.shell > client.1023: . ack 6 win 1448 <略>
IP server.1023 > client.1022: S 1768835748:1768835748(0) win 5840 <略>
IP client > server: icmp 68: host client unreachable - admin prohibited
IP server.shell > client.1023: F 1:1(0) ack 6 win 1448 <略>
IP client.1023 > server.shell: . ack 2 win 1460 <略>
IP client.1023 > server.shell: F 6:6(0) ack 2 win 1460 <略>
IP server.shell > client.1023: . ack 7 win 1448 <略>

途中までは同じです。最初にSYN, SYN ACK, ACKでクライアント→サーバに接続が張られ、

client:1023 → server:514(shell)にSYN
client:1023 ← server:514 SYN ACK
client:1023 → server:514 ACK

メッセージを1つ投げてから(たぶんポート番号)、

client:1023 → server:514 メッセージ
client:1023 ← server:514 ACK

サーバがクライアントの1022番を空けようとします。で、拒否されるので、

client:1022 ← server:1023 SYN(接続しようとする)
client      → server ICMP reject

接続が切られてしまいます。

client:1023 ← server:514 FIN(切断)
client:1023 → server:514 FIN ACK
client:1023 → server:514 FIN(切断)
client:1023 ← server:514 FIN ACK

これは私の想像ですが、rshはサーバ側でコマンドを実行してしまう、けっこう危険なサービスなので、設計として、クライアント側をかなり信頼する根拠が必要であると考えているのではないかと思います。あるいは、stdin/stdout用のポートとstderrのポートを分けてるとか??

とにかく、rshでプログラムを実行中は2つの接続が確保された状態になっていますし、片方はクライアントからサーバの514番への接続、片方はサーバからクライアントへの接続です。なので、クライアントのポートを開けておかないとrshは使えません。

ちなみに、rshのソースを見ても何も分かりません。glibcのrcmd(3)という関数を呼んでいるだけです。「poll: protocol failure…」のメッセージもこの先で出してます。glibcのinet/rcmd.cとかを読むと意味が分かるかもしれませんね。circuit setupというのはクライアントからサーバに接続して、サーバからクライアントに接続すると一周してサーキットになるとか、そんな言葉なのかもしれませんね。

他にもけっこう不思議な現象もあったように記憶してますが(片方がSolarisのときとか)、長くなるのでこのへんにしときます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です