Closed ddddddO closed 5 months ago
現状ダメそう、rstパケットがカーネルから送られるっぽい なので、一旦はtcpより上のレイヤーは、
net.Conn
に書き込む、でいける気がするebpfは利用できないか https://zenn.dev/hidenori3/articles/e1352e8cfeb2af
他の自作してるの 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://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%85 と https://github.com/sat0ken/go-tcpip/blob/fc2b35be0ca462df93c33c22b0081c06ee4c8788/socket.go#L10
の辺り見るとできそう
だったけど、ちょっとできなかった そのときのコミット(コメントアウト部分がそれら。消した関数あるけど)
環境によって違ったりしそう?それかやっぱり自分の実装が悪いのかも
TCP使うアプリケーションレイヤーは、3way handshake + (tls の handshake) + fin というのがあって、仮にそれを任意入力でパケット作ってもらうとして、どこかにでもミスったらアプリケーションレイヤーまでのパケットが正確に飛ばないはずだし、利用者そこまでしたいかな...? 一旦、アプリケーションレイヤーまでの単品のパケットは飛ばせるし、それでいいんではと思う(3wayhandshake する・しないの選択肢は出す)
ebpfでいけないかな tcpのsynパケット送ったときの送信元ポート番号を送信元ポートに持つカーネルから自動送信されるrstパケットはドロップするまたは送信させない、みたいなこと
https://zenn.dev/masibw/articles/068bdfe5edee17 「Traffic Control」
3way handshakeするしないのチェックボックスはそのままで、内部の実装として自前で用意したい
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 のあたりも参考になりそう
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は大丈夫そう
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.
のあたりやる必要があるのかどうか。
今回カーネルで自動的に送られるrstパケットのtcp flagは0x014
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'
User-agent の指定がちゃんとしてないと、nc以外で起動したWebサーバーからレスポンスがないとかあるかな?
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/User-Agent
↑ではなさそうで、もしかするとtimestamp optionをちゃんと入れてやり取りしないとダメかも そのようで、一旦、こっちから送る分にはoptoinつけずにやったら、nc 以外のWebサーバーでもhttpレスポンスが返ってきた
修正版
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
次はfin
3wayhandshake ~ http get ~ fin/ack までいけた
あとは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 側に最低限の実装はできそう
対応はできた
https://hb.matsumoto-r.jp/entry/2017/02/16/094040 この辺り読むとなんとかなりそう?