CubicLouve

Spring_MTの技術ブログ

Macで自由にパケットのフィルタリング、帯域制限、パケロス率の設定をする

Macにおいて、ネットワーク帯域の制御などはNetwork Link Conditionerで対応可能です。

下記ページよりAdditional Tools for Xcode を探してdmgをダウンロードし、その中にあるNetwork Link Conditioner.prePane からインストール可能です。

https://developer.apple.com/download/all/

そうすると、システム環境設定の中にNetwork Link Conditionerがあるので、そこから利用可能です。

このNetwork Link Conditionerを利用すれば、帯域幅の制限やパケロス率の設定などを簡単に実現できます。

ただし、UDPパケットを全部落としつつ、TCPパケットについて帯域幅やパケロス率を設定したいという複雑なネットワーク環境を再現するためにはNetwork Link Conditionerだけでは実現できませんでした。

そこで、macOSにある、packet filterとdummynetを組み合わせることでこのような複雑なネットワーク環境を再現できました。

この記事ではpacket filterやdummynetの仕組みを紹介しつつ、どのように設定すれば、このような複雑なネットワーク環境を再現できるかをご紹介します。

実際 、Network Link Conditionerはpacket filterやdummynetをGUIからうまく設定できるような感じになっています。

packet filter(pf)

packet filter(pf)は、TCP/IPのフィルタリングとアドレス変換行うOpenBSDでの仕組みです。

macOSBSD系OSなので、pfを使うことでTCP/IPのフィルタリングを行うことになります。(iptablesとかではない)

pf.conf

packet filterの設定ファイルになります。

ここでパケットフィルターの設定をします。

macOSだと、/etc/pf.conf というファイルが最初からあるかと思います。

ここでは、 pf.conf において、パケットフィルタリングについての設定についてのみ言及します。

特定のIPアドレスからのUDPパケットを落とす設定例は下記のとおりです。

block return in proto udp from 192.0.2.1 to any
  • アクション(1つ目の区切り) パケットをブロックするための block というアクションを指定しています。 2つ目の指定で return としていますが、これは、tcpパケットに対して TCP RST を返し、UDP およびその他のパケットに対して ICMP UNREACHABLE を返すようにするという指定です。 単純に落とすだけであれば、drop を指定してください。

  • in以降のオプション in ( または out ) を指定することで、 受信パケット(送信パケット)を対象にするかを指定します。

proto で対象となるprotocolを指定します。今回は udp を指定しています。

from と toでそれぞれ、送信元アドレスやポート 宛先アドレスやポートを指定します。

他でできることは、 man pf.conf で確認してもらえると。

他にもアクションは様々設定できます。

pfctlコマンドとオプション(抜粋)

pfctlコマンドを利用して、packet filterの状況やpf.confの反映を行います。

確認オプション

-s のあとに続く文字列で取得できるもの選べます。

-v をつけることでより詳細な情報をみれるのと、-v を複数回書くことで詳細度が上がります。

気をつけたいのは、 -vvv とかではなく、 -v -v などと複数回書く必要があることです。

-si or -s info

filterの統計情報などが見れます

-sr or -s rules

現在ロードされているルールを表示します。

反映

-f でルールの反映を行います。 ファイル or 標準出力でも可能。

n をつけることで実際には反映させずparseだけ行うようにできます。

dummynetとdnctlコマンド

dummynetは帯域のコントロール、ネットワークトラッフィクの遅延やパケロス率の制御などを行えるネットワークのエミュレーターです。

いわるゆtraffic shaperですね。

BSD系のOSに組み込まれており、macOSにも標準でインストールされています。

このdummynetはdnctlコマンドで制御を行います。

dnctlコマンドではpipeを使って帯域幅、遅延、キューサイズ、パケロス率を設定できます。

コマンド例

dnctl pipe 1 config delay 250ms bw 1Mbit/s plr 0.1

ここでは、遅延250 ms 、帯域幅 1M bit/s、パケロス率10%を pipe 1に設定するコマンドになっています。

dnctlだけではこの設定はつかわれません。

packet filterを使ってdummynetの設定にトラフィックを流すようにします。

この設定については、dnctlのmanにしかなく、pf.confのmanには記載されていないので要注意です。

pf.confには下記のように設定します

dummynet in quick proto tcp all pipe 1

この場合tcpのパケットがpipe 1のdummynetを通ることになります。

dnctlで設定した内容は

dnctl pipe show

こんな感じで見れます。

全部合わせてみると

UDPパケットを全部落として、TCPパケットについてはパケロス10%遅延250ms 帯域 1M bit /s にしてみます。

dnctlで下記を設定

dnctl pipe 1 config delay 250ms bw 1Mbit/s plr 0.1

pf.confには下記を設定

block return in proto udp from 192.0.2.1 to any
dummynet out quick proto tcp all pipe 1

参考

OpenBSD PF: User's Guide

PF: OpenBSD パケットフィルター

トラフィックシェーピング - Wikipedia

パケットフィルタ規則の構文 - Oracle® Solaris 11.3 でのネットワークのセキュリティー保護

http://info.iet.unipi.it/~luigi/dummynet/

https://www.jstage.jst.go.jp/article/itej/64/10/64_1473/_pdf

Bandwidth Throttling on macOS - Lei's Blog

qiita.com