2020-07-06 TCP_SAVE_SYNとTCP_SAVED_SYNの簡単まとめとtcprivのリファクタリングやテストなど

  • TCP_SAVE_SYNとTCP_SAVED_SYNについて簡単にまとめておく(これらのオプションは微妙に意味が違うので注意)
    • ほぼ説明の情報が無いのでコードを読んで理解したのであっているはず
  • これらのオプションは基本的にサーバ側の実装で行うものでsetsockoptを使ってlisten前のfdにTCP_SAVE_SYNを立てておく
    • クライアント側では特にフラグなどたてる必要なし
  • その後listenしてacceptしている状態で、クライアントからコネクションが来てacceptされたあとのfdに対して、getsockoptによってTCP_SAVED_SYNを立ててgetするとvalueにsynパケットのヘッダ情報が一度だけコピーされる
    • このvalueはIPヘッダの1bit目から取得可能で4bit右シフトすると0x4などが得られる
    • IPヘッダとTCPヘッダをまとめた最大60バイト分のビット列が得られるので、それをcastやmemcpyするなどして値を取得すれば良い
      • 当たり前だがエンディアンの扱いには注意すること
    • なんで、TCPオプションなどに何らかの情報を埋め込んでいるときなどはそれをサーバ側のユーザランド実装で一度だけ簡単に取り出すことができる
      • 実際にこれを提案したgoogleもfingerprintなどを埋め込んで簡単に扱えるみたいなことを提案の中に書いていた
        • 僕がいまやろうとしているプロセスのオーナ情報を埋め込んで多要素認証的にプロセス単位での認証認可を行う仕組みとなにか近いことをやっているのかな、というイメージ
          • この研究の背景はこちら

hb.matsumoto-r.jp

  • セッションを貼ったあとにそのセッションのsynヘッダをユーザーランドで取り出すことはできなかったし、カーネルでも何かしらどこかに保存しておかないとできなかったが、2015年ぐらいのgoogleの提案で今のカーネル5系や4系などではこの機能が取り込まれており使える
    • 挙動や背景はこのパッチを見たら一目瞭然なのでこれを見ると良い

lwn.net

  • ただ、ubuntu20.04などではカーネルで対応しているものの、ユーザランド側でのオプションフラグを定義したヘッダなどはなさそうなので自分で#define TCP_SAVED_SYN 28 とかしてやれば使える

  • synパケットのヘッダの遅延取り出しを完全に理解したので、tcprivのサーバ側実装はもはやユーザランドだけでよくなったのでそれに対応
  • それなりに苦労して勉強して書いていったカーネルモジュールも、勉強すればするほど便利な書き方や使い方を思いついて、最終的に今日のブラッシュアップでは実装の行数は半分以下になりそうである。これが実装と設計とサーベイと見直しを高速に回すメリットであるがなぜか少しだけ勿体無さを感じるw
    • これテストどうしよっかと頭抱えていたけど、テストのPoCも完全にできたし、人間って考えるだけじゃなくて手を動かしているうちに思考の限界を突破していくの本当にすごいな。
  • 大体最小実装でtcprivのやりたことが実現できたので、あとは評価をどうやるか考える
    • identdと性能比較とか思っていたけど、明らかに性能に差がでそうで意味なさそうだし、NAT超えできないことも踏まえると要件も違うからいつもどおりどれぐらいオーバヘッドあるかを調べるのが良いか
    • DBの認証に使うとかいっていたけど、DBの認証でも明らかにオーバヘッドなさそうだからどうしようかなぁ、リアルシステムで使えるような議論に持っていける良い評価軸とベースラインを考えていく
  • この辺の研究がおちついてきたらmod_fileownercheckの論文も書いていきたい

  • ガンダムファンクラブに入って最高の気持ち
  • 写真をあげるとたくさんいいねがもらえるしガンダム見放題だし最高
  • メカ系フィギュア欲が高まりに高まっており、週末の魂featureも最高に刺激を得た
  • メタルビルドやメタルロボット魂、ホットトイあたりをしっかり攻めていきたい1

  • 今夜はうちおさん主催のC言語勉強会に参加する
  • 楽しかったのでコード書いてた