ddddddO / packemon

Packet monster (っ‘-’)╮=͟͟͞͞◒ ヽ( '-'ヽ) TUI tool for sending packets of arbitrary input and monitoring packets on any network interfaces (default: eth0).
BSD 2-Clause "Simplified" License
89 stars 0 forks source link

3way handshakeの希望 #17

Closed ddddddO closed 5 months ago

ddddddO commented 5 months ago

https://hb.matsumoto-r.jp/entry/2017/02/16/094040 この辺り読むとなんとかなりそう?

ddddddO commented 5 months ago

現状ダメそう、rstパケットがカーネルから送られるっぽい なので、一旦はtcpより上のレイヤーは、

ddddddO commented 5 months ago

ebpfは利用できないか https://zenn.dev/hidenori3/articles/e1352e8cfeb2af

ddddddO commented 5 months ago

他の自作してるの https://twitter.com/voluntas/status/1755760900819353712?t=w9FYiBYIDmpmYGE3w7LS1Q&s=19

今回参考になりそうなのは以下あたり以降 https://docs.google.com/presentation/d/11ypJfle9WWrFNkhbgnDSM9PW5acyRtzQ_p0_CE1aENg/edit#slide=id.gd2c870f180_0_430

OSから自動で返されるっぽいrstパケットの制御についてない?それか構造体(資料で言う pcb 構造体でなんらか制御が入ってる?)

この辺りにpcbについて https://docs.google.com/presentation/d/1YIFecvNASn1iz3ps_OvrXoL02IJ-cs6_i8WBkukMKpo/edit#slide=id.g7a37e3e8cb_0_1066

なんだかいけそう?

ちょっとわからなくなってきた

https://docs.google.com/presentation/d/1_fTLvWuNkJ0cpQFKQ1m-J58nAX2kCSe8DujD7RiyStA/edit#slide=id.gd3283b5d32_0_1105

https://github.com/pandax381/microps/blob/master/app/tcpc.c

上のコードで行くと、

https://zenn.dev/satoken/articles/golang-tcpip#%E3%82%AA%E3%83%AC%E3%82%AA%E3%83%AC%E3%83%8F%E3%83%B3%E3%83%89%E3%82%B7%E3%82%A7%E3%82%A4%E3%82%AF%E3%81%AE%E5%AE%9F%E8%A3%85https://github.com/sat0ken/go-tcpip/blob/fc2b35be0ca462df93c33c22b0081c06ee4c8788/socket.go#L10

の辺り見るとできそう

だったけど、ちょっとできなかった そのときのコミット(コメントアウト部分がそれら。消した関数あるけど)

環境によって違ったりしそう?それかやっぱり自分の実装が悪いのかも

ddddddO commented 5 months ago

TCP使うアプリケーションレイヤーは、3way handshake + (tls の handshake) + fin というのがあって、仮にそれを任意入力でパケット作ってもらうとして、どこかにでもミスったらアプリケーションレイヤーまでのパケットが正確に飛ばないはずだし、利用者そこまでしたいかな...? 一旦、アプリケーションレイヤーまでの単品のパケットは飛ばせるし、それでいいんではと思う(3wayhandshake する・しないの選択肢は出す)

ddddddO commented 5 months ago

ebpfでいけないかな tcpのsynパケット送ったときの送信元ポート番号を送信元ポートに持つカーネルから自動送信されるrstパケットはドロップするまたは送信させない、みたいなこと

https://zenn.dev/masibw/articles/068bdfe5edee17 「Traffic Control」

3way handshakeするしないのチェックボックスはそのままで、内部の実装として自前で用意したい

ddddddO commented 5 months ago

xdp は ingress のトラフィックのみ扱うようで、egress 扱いたければ tc (traffic control) を利用するよう

以下に traffic control と ebpf についてのblogサンプルコードあり https://fedepaol.github.io/blog/2023/04/06/ebpf-tc-filters-for-egress-traffic/

SEC マクロについて https://ebpf-go.dev/concepts/section-naming/

https://ebpf-go.dev/concepts/section-naming/#program-sections のあたりの使えばいいのかな 使うなら tc になるのかな

https://eunomia.dev/tutorials/20-tc/#overview-of-tc のあたりも参考になりそう

ddddddO commented 5 months ago

https://github.com/ddddddO/work/tree/master/go/ebpf/tc

egress な arpリクエストをdropできたのでrstパケットもdropできるはず あと足りないのは、ユーザ空間からebpfのmapに書き込んだ情報ですぐにloadされたebpfプログラムでdropできるかどうかの検証

時間がかかりそうなのは、c風言語でtcpパケット構築すること...全部は構築しなくていいはずかな https://github.com/cilium/ebpf/blob/main/examples/tcprtt/tcprtt.c のあたり参考に出来そう

https://man7.org/linux/man-pages/man8/tc-bpf.8.html のコードも参考になりそう

あと、packemon終了時にebpfプログラムのデタッチだったかがをしないとダメそう pc再起動しないとそのポートのrstパケット送れないなんてことになりそう

別問題で、Generator のSend時に落ちる arp以外のsendは大丈夫そう

ddddddO commented 5 months ago

bpftool いれる https://qmonnet.github.io/whirl-offload/2021/09/23/bpftool-features-thread/

https://github.com/libbpf/bpftool

Download a precompiled LLVM release or build it locally.

のあたりやる必要があるのかどうか。

ddddddO commented 5 months ago

今回カーネルで自動的に送られるrstパケットのtcp flagは0x014

ddddddO commented 5 months ago

https://github.com/ddddddO/work/commit/4a7396d2dc1ae9ff08beecdebab03a6aff9a3787 のコミット時点のebpfプログラムをロード後、https://github.com/ddddddO/packemon/tree/6a1b5ec1a97b043cfb9fe18f97f771cde163d148 のコミットで、以下実行で、自前で3way handshake してhttpすることできた

 sudo go run cmd/packemon/main.go --send --debug --proto tcp-3way-http

再度試すには、以下を変えた上で全て揃えること

また、raspberry piでは以下でhttp server起動しておくこと

# https://sonots.livedoor.blog/archives/34703829.html
sudo bash -c 'trap exit INT; while true; do ( echo "HTTP/1.0 200 Ok"; echo; echo "Hello World" ) | nc -l 80; done'
ddddddO commented 5 months ago

User-agent の指定がちゃんとしてないと、nc以外で起動したWebサーバーからレスポンスがないとかあるかな?

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/User-Agent

↑ではなさそうで、もしかするとtimestamp optionをちゃんと入れてやり取りしないとダメかも そのようで、一旦、こっちから送る分にはoptoinつけずにやったら、nc 以外のWebサーバーでもhttpレスポンスが返ってきた

ddddddO commented 5 months ago

修正版

https://github.com/ddddddO/work/commit/4a7396d2dc1ae9ff08beecdebab03a6aff9a3787 のコミット時点のebpfプログラムをロード後、https://github.com/ddddddO/packemon/tree/957c0e288a5c37de8830e82935d3dadd003b81e5 のコミットで、以下実行で、自前で3way handshake してhttpすることできた

 sudo go run cmd/packemon/main.go --send --debug --proto tcp-3way-http

再度試すには、以下を変えた上で全て揃えること

また、送信先のIP・MACアドレスが違ってるかもなので、一回curlした結果のパケットキャプチャ見てIP・MACアドレスも編集必要になるかも

また、raspberry piでは以下でhttp server起動しておくこと

sudo go run main.go

tcp_3wayhandshake

ddddddO commented 5 months ago

次はfin

ddddddO commented 5 months ago

3wayhandshake ~ http get ~ fin/ack までいけた tcp_3wayhandshake_finack

あとはebpf側の検証残 qdiscをaddするようにしてdelすればよさそう? https://github.com/lizrice/learning-ebpf/blob/83446f0a798ed06b29c5a33dc60ffc5081ff1821/chapter8/network.py#L52

それでokだった https://github.com/ddddddO/work/tree/c327b54455d81a5852280ba6010a28f6180768e5/go/ebpf/tc

なので、packemon 側に最低限の実装はできそう

ddddddO commented 5 months ago

対応はできた