Zenn
🙌

EtherIP(RFC3378)をRustで実装した話ってよ

2025/03/16に公開

こんにちは、自称インチキ高校生の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:
https://docs.rs/tokio/latest/tokio/io/unix/struct.AsyncFd.html

最後に

実装してみたのですが、動かなかったりして結構大変でした。自作したいなって思う方は下にRust版EtherIPの実装リポジトリを置いておくので、見ておいてください。

Repo:
https://github.com/tuna2134/etherip

GitHubで編集を提案

Discussion

ログインするとコメントできます