ページ 11

各種ブラウザのTCPハンドシェークフラグ操作への対応について

Posted: 2018年8月02日(木) 08:59
by osaka-tc
uNet3の各種WEBブラウザのTCPハンドシェークフラグ操作への対応について、少しアドバイスをいただけないでしょうか?

現在、uNet3 TCP/IPスタック上に、独自WEBサーバを実装中です。
ほぼ実装しておりますが、Wireshark観測結果を確認すると、各種WEBブラウザからのTCPコネクションのハンドシェークフラグ操作に応答できず、
[TCP Suprious Retransmission]が検出されています。
下記のようなケースでWEBブラウザより、「SYN」が発行されることに起因しています。

最新Google Chrome (ver 68.0.6440.75)のケースでは、HTTP GETコマンド発行時(下記④)に、
①SYN    :ブラウザ→WEBサーバ
②SYN+ACK :WEBサーバ→ブラウザ
③ACK    :ブラウザ→WEBサーバ
④SYN    :ブラウザ→WEBサーバ    ←少し後で[TCP Suprious Retransmission]として検出される
⑤RST+ACK :WEBサーバ→ブラウザ

また、GETコマンド応答返信時(下記⑦)に、
①フラグメントデータ :WEBサーバ→ブラウザ
②ACK          :ブラウザ→WEBサーバ
③フラグメントデータ
④ACK
⑤フラグメントデータ
⑥ACK
⑦フラグメントデータ
⑦SYN         :ブラウザ→WEBサーバ  ←少し後で[TCP Suprious Retransmission]として検出される
③RST+ACK :WEBサーバ→ブラウザ
⑧ACK
⑨フラグメントデータ
⑩ACK

このように、予期せぬところで「SYN」が発行されると、「RST+ACK」がWEBサーバ側から発行されます。
通常の3Wayハンドシェーク想定外の「SYN」の発行に対応しているようなのですが、問題はないと考えてよいでしょうか?
ブラウザのこのような動作の意図をご教示いただけないでしょうか?
また、uNet3としては、このような意図を想定していますでしょうか?
ちなみに、仮WEBサーバ実装としては、問題なく機能しています。

宜しくお願いいたします。

Re: 各種ブラウザのTCPハンドシェークフラグ操作への対応について

Posted: 2018年8月02日(木) 22:17
by eForce技術担当
お世話になっております。
イー・フォースの技術担当です。

情報が少ないので、一部こちらの想像で書かせていただきます。

>①SYN    :ブラウザ→WEBサーバ
>②SYN+ACK :WEBサーバ→ブラウザ
>③ACK    :ブラウザ→WEBサーバ
>④SYN    :ブラウザ→WEBサーバ    ←少し後で[TCP Suprious Retransmission]として検出される
>⑤RST+ACK :WEBサーバ→ブラウザ

本件ですが、LISTEN状態のソケットがないために④のSYNに対して⑤でRST+ACKを返信しています。
具体的にはローカルポート番号を80に設定したソケットを1つ用意して、そのソケットを引数にcon_soc( )していると思いますが、
③の時点でTCPのコネクションが生成され、ソケットがLISTEN状態でなくなります。
他にLISTEN状態のソケットがないので、④のSYNに対して⑤でRSTを返信しているのではないかと思います。

弊社からお客様へご提供しているHTTPサーバでもコンフィグレーションによっては、
同様の現象が発生します。

・参考 : HTTPサーバが正常に動作しません。
 1. Webブラウザからの SYN に対して RST を返却してしまい、ページが表示されない。
 viewtopic.php?f=13&t=139

対策としては、ローカルポート番号を80番に設定したソケットを引数にcon_soc( )を実行してください。
同じローカルポートに設定した、複数のソケットを同時にcon_soc( )を実行することは可能です。
通信相手(今回のケースではWEBブラウザ)から接続要求があると順にcon_soc( )が完了します。

具体的には複数のタスクを用意して次のようにしてください。
タスクとソケットの数が多いほど、WEBブラウザから同時接続できる数が多くなります。

コード: 全て選択

タスク1:
    while(1) {
        con_soc(ソケット1, ..., SOC_SER);
        ...
        HTTPのリクエストを処理
        ...
        cls_soc(ソケット1, ...)
    }

タスク2:
  while(1) {
          con_soc(ソケット2, ..., SOC_SER);
          ...
          HTTPのリクエストを処理
          ...
          cls_soc(ソケット2, ...)
     }

タスクN:
  while(1) {
          con_soc(ソケットN, ..., SOC_SER);
          ...
          HTTPのリクエストを処理
          ...
          cls_soc(ソケットN, ...)
          
     }

>通常の3Wayハンドシェーク想定外の「SYN」の発行に対応しているようなのですが、問題はないと考えてよいでしょうか?

①~③と④~⑤はポート番号が異なると思います。
従って①~③と④~⑤はそれぞれ別のセッションとなります。
また、④の時点で、80番のポートでcon_soc( )を実行しているソケットがないので、RSTをブラウザへ返信するのは正しい動作
となります。

>ブラウザのこのような動作の意図をご教示いただけないでしょうか?
ブラウザの実装者の意図は正確には分かりませんが、
下記のサイトが参考になるかと思います。

・各ブラウザの同時接続数を変更する方法
 https://novlog.me/win/win10-browser-set ... onnection/

Re: 各種ブラウザのTCPハンドシェークフラグ操作への対応について

Posted: 2018年8月07日(火) 08:15
by osaka-tc
回答ありがとうございます。

当方ブラウザの知識が薄く、現象から頷ける内容でした。
早々に、並列ソケット化(マルチタスク化)して検証しました。
結果、RST/ACK , Dup ACK , Retranmission等のTCPパケットは消えました。

未だ、接続途中、通信途中でのケーブル切断の特殊なテストケースで、ノンブロッキング
・コールバックが発生しなくなる場合があり、引き続き検証中です。

ありがとうございます!