🙌
EtherIP(RFC3378)をRustで実装した話ってよ
こんにちは、自称インチキ高校生のtuna2134です。
今回Rustを使ってEtherIPを実装してみました。なので、RFC3378の解説をしつつ、実装を説明しようと思います。
そもそもEtherIPってなんですの?
RFC3378に定義されているプロトコルで、Ethernetフレーム(L2)をカプセル化して、IPプロトコル97番を使って転送することです。要はL2TP VPNと同じ仕組みですね。主にNEX IXなどといった業務用ルーターに入っている機能なのですが、Linuxでは標準でないので、使いたいときは自作するなりする必要があります。(Linuxに搭載されてなかったおかげで勉強する機会を与えてくれたのでとても感謝をしています!)。
RFCを読み解く時間だってよ
詳しい説明はRFCを読まないとわかりません。なので重要なところをいくつか抽出するので、ついてきてくださいな。
全体的なパケット構造
まずパケットの構造から!
+-----------------------+-----------------------------+
| | | |
| IP | EtherIP Header | Encapsulated Ethernet Frame |
| | | |
+-----------------------+-----------------------------+
名前 | 説明 |
---|---|
IP | IPプロトコルのヘッダー部分です。ここでは取り扱いません。 |
EtherIP Header | ここはEtherIPのバージョンなどが格納されているEtherIPのヘッダー部分です。結構重要なので後々説明します。 |
Encapsulated Ethernet Frame | カプセル化されたEthernetフレーム。そこそこ重要です。 |
EtherIP Headerの詳細
EtherIP Headerの構造です!
数字の単位はbitsです。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | |
| VERSION | RESERVED |
| | |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
名前 | サイズ | 説明 |
---|---|---|
VERSION | 4bits | EtherIPのバージョンです。3(0b0011)をここにおいてください。 |
RESERVED | 12bits | 将来的に何かに使うために確保されている空間です。0をここにおいてください。 |
送信及び受信
TCPやUDPを使うわけではないです。IPプロトコル97番を使います。
Rustで実装した際の話
Rustで使ったライブラリなど少しだけします。
使用したライブラリ
ほかにもいろいろありますが、今回利用したのは以下です。
- tun
- socket2
- tokio
- bytes
IPプロトコル関係
tokioとかにはIPプロトコルを触るライブラリなどが用意されてません。そこでtokioのAsyncFd
を利用して、socket2::Socket
を非同期にラッピングしました。
Ref:
最後に
実装してみたのですが、動かなかったりして結構大変でした。自作したいなって思う方は下にRust版EtherIPの実装リポジトリを置いておくので、見ておいてください。
Repo:
Discussion