レートリミットとは通信量の制限のこと。ここではアプリケーションレベルのレートリミットではなく、OS全体のレートリミットについて扱う。
Linuxにおけるレートリミットは、1.ファイアウォール(iptablesやnftables)か、2.トラフィック制御(tcコマンド)を用いて設定することができる。
ここでは1のうち、nftablesを用いたレートリミットの設定を扱う。
1.nftablesによるレートリミットの設定方法
参考リンク:https://wiki.nftables.org/wiki-nftables/index.php/Rate_limiting_matchings当然だが、ファイアウォールに他のルールを設定している場合は、ルールの順番を間違えたりすると意味がなくなるので注意すること。
nftablesの他の機能と組み合わせれば、送信先ポートや送信元アドレスごとのリミットレートも設定できる。
1.1 基本
nft add rule inet filter input limit rate 10 mbytes/second accept
nft add rule inet filter input drop
limit rate
のキーワードを使うと、指定した通信量以下のパケットのみにマッチさせることができる。上のルールで、1秒につき10メガバイトまではacceptし、その基準を超えたパケットは下のルールによってdropされる。
(ちなみに、パケットを廃棄してしまうと確立した接続が途中で突然切れないか心配になるかもしれない。しかし、TCPの仕様でパケットはすぐに再送されるので、接続がいきなりブツッと切れるみたいなことはそんなにないはず)
パケット数で指定することもできる。
nft add rule inet filter input limit rate 100/second accept
nft add rule inet filter input drop
1.2 burst
nft add rule inet filter input limit rate 10 mbytes/second burst 9000 kbytes accept nft add rule inet filter input drop
1秒につき10メガバイトの通信量を超えたときも、あと9000キロバイトまでなら一時的に許可される(あくまで一時的なので、常時この通信量が許可されるわけではない)
1.3 limit rate over
単にlimit rate
の場合は指定した通信量以下の場合にマッチするルールになったが、limit rate over
の場合は指定した通信量を超えたときにマッチするルールになる。nft add rule inet filter input limit rate over 10 mbytes/second drop
こちらを使ってdropしたほうがシンプルで、使い勝手が良いかもしれない。
burstも設定できる。
nft add rule inet filter input limit rate over 10 mbytes/second burst 9000 kbytes drop
1.4 速度計測
設定したルールが上手く動いているか確認したいときは、https://www.speedtest.netなどのサイトで手軽に速度を確認することができる。仮想OS等を使って、iperf3などで計測してみるのも良い。
注意点として、通信速度によく使われる単位である「Mbps」(bが小文字)は、一秒あたりの通信量をメガビット(メガバイトではなく)で表したものであることには気をつけること。
1.5 IPアドレスごとの通信量制限
参考リンク:https://wiki.nftables.org/wiki-nftables/index.php/Meters
https://www2.filewo.net/wordpress/2019/10/19/2206/
setを用いることでIPアドレスごとのレートリミットの設定が可能になる。
nft add set inet filter rate_limit_ip {type ipv4_addr \; flags dynamic \; timeout 10m \;} nft add rule inet filter input update @rate_limit_ip { ip saddr limit rate over 10 mbytes/second } drop
まずIPアドレスのsetを作成する。このときflags dynamic \;
を指定するのがポイントで、動的にアドレスを管理できるようになる。
(timeoutはsetが溢れないために設定しておく)
@をつけてsetを呼び出し、随時updateすることでIPアドレスごとのレートリミットが設定できる。
IPv6も同様に設定できる。
nft add set inet filter rate_limit_ipv6 {type ipv6_addr \; flags dynamic \; timeout 10m \;} nft add rule inet filter input update @rate_limit_ipv6 { ip6 saddr limit rate over 10 mbytes/second } drop
2.ルールセットの例
レートリミットを使用したnftablesルールセットをいくつか書いておく。2.1 SSHサーバへの新規接続に制限を設けた例
table inet filter { chain input {type filter hook input priority filter; policy drop; ct state established,related accept ct state invalid drop iif "lo" accept meta l4proto icmp accept meta l4proto ipv6-icmp accept tcp dport 22 ct state new limit rate over 20/minute drop tcp dport 22 accept } chain forward {type filter hook forward priority filter; policy drop;} chain output {type filter hook output priority filter; policy accept;}}
2.2 HTTP(HTTPS)サーバで同一アドレスからの通信量と新規接続を制限した例
table inet filter {set rate_limit_ip {type ipv4_addr size 65535 flags dynamic,timeout timeout 10m}set rate_limit_ipv6 {type ipv6_addr size 65535 flags dynamic,timeout timeout 10m}set rate_limit_newconnection_ip {type ipv4_addr size 65535 flags dynamic,timeout timeout 10m}set rate_limit_newconnection_ipv6 {type ipv6_addr size 65535 flags dynamic,timeout timeout 10m} chain input {type filter hook input priority filter; policy drop; ct state established,related accept ct state invalid drop iif "lo" accept meta l4proto icmp accept meta l4proto ipv6-icmp accept tcp dport {80, 443} update @rate_limit_ip { ip saddr limit rate over 20 mbytes/second } drop tcp dport {80, 443} update @rate_limit_ipv6 { ip6 saddr limit rate over 20 mbytes/second } drop tcp dport {80, 443} ct state new update @rate_limit_newconnection_ip { ip saddr limit rate over 20/second } drop tcp dport {80, 443} ct state new update @rate_limit_newconnection_ipv6 { ip6 saddr limit rate over 20/second } drop tcp dport {80, 443} accept } chain forward {type filter hook forward priority filter; policy drop;} chain output {type filter hook output priority filter; policy accept;}}
3. 参考リンク
https://wiki.nftables.org/wiki-nftables/index.php/Main_Pagehttps://netfilter.org/projects/nftables/manpage.html
https://wiki.archlinux.jp/index.php/Nftables