ipset で IPアドレス(またはネットワークアドレス)からの接続を許可する
linux のFWを使うのにアドレス条件を指定すると記述量が半端なく長くなる。
これを解消するために、ipset というコマンドがあり、IPアドレスやネットワークアドレスをグループ化して管理するコマンドがある。これについては以前も記述した。以前の記述が不明確でわかりづらいので書き直す事にした。→ 以前の記事
今回は、ローカルネットワークやローカルネットワーク内の指定ホストからの接続を許可する例を書きます。
それをipsetで書いて、ipsetの使い方を見てゆこうと思います。
iptablesとipsetでポートへのアクセスをIPアドレス(ネットワーク)単位で制御する。
ipset と iptablesを組み合わせて使うと理解しやすくメンテしやすいFWの記述ができる。
準備:インストール
実験に使っているのは、いつもRaspbianなので、apt をつかいます。
sudo apt install ipset
ipset でリストをつくります。
ipset ではネットワークアドレスやIPアドレスを、グループ化して管理するため「リスト」と呼ばれるものを作ります。
今回は、ローカルアドレスを表すリスト(my_hosts)と、ローカルネットワークを表すリスト(my_local )の2つを作ることにします。
リストの作成:ローカルアドレス
リストを作成します。hash:ip
はこのリストが、IPアドレスの列挙であると明示しています
# ipset create my_hosts hash:ip
リストの削除
リストを削除するには次のようにします。
# ipset destroy my_hosts
リストに、IPアドレスを追加します。
追加するIPアドレスはローカルのLAN内にいるIPアドレスのつもりです。
# ipset add my_hosts 192.168.11.1 # ipset add my_hosts 192.168.1.1 # ipset add my_hosts 192.168.255.1
追加した結果を確認します
# ipset list my_hosts Name: my_hosts Type: hash:ip Revision: 4 Header: family inet hashsize 1024 maxelem 65536 Size in memory: 124 References: 0 Members: 192.168.1.1
リストから項目の削除
項目を指定して削除するには次のようにします。間違ったときや不要になった時に使うと良いでしょう。
# ipset del my_hosts 192.168.11.1 # ipset del my_hosts 192.168.1.1 # ipset del my_hosts 192.168.255.1
ネットワークアドレスのリストを作成
IPアドレスだけでなく、ネットワークアドレスでの範囲指定を単位としたリストを作ることが出来ます。
今度は hash:net
をつかいます。先ほどは hash:ip
だった。
# ipset create my_local hash:net
ネットワークアドレスのリストへの項目の登録と削除と確認。
これも先ほとど同じです。
# ipset add my_local 192.168.11.0/24 # ipset dell my_local 192.168.11.0/24 # ipset list my_local
再起動後にも設定が維持されるようにする。
ipset が再起動後にもまたロードされる様に、設定を保存する。また、再起動後にロードさせる設定をsystemd に連携させる。
設定の保存
sudo ipset save -f /etc/ipset.conf
設定のロード(リストア)
sudo ipset restore -f /etc/ipset.conf
再起動後にロードさせる systemd 設定をつくる
/etc/systemd/system/ipset.service
[Unit] Description=ipset restore Before=networking.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/sbin/ipset restore -exist -f /etc/ipset.conf [Install] WantedBy=network.target
どのサービスに入れるかは判断の分かれるところなので、明確な解答はないですね。 iptables やnetworn.serviceのサービス定義の ExecStartPre
でも良いと思います。
また、ipset は iptablesと共に使われるので、iptablesの起動設定に含めたり、/etc/network/if-pre-up.d/
に記述するのいいともおいます。
iptablesの記述にipsetを使う。
ipsetを保存とリロードが出来たら、iptablesの設定に追加していきます。
my_local からの ssh(tcp/22) 接続を許可する霊
-I INPUT -m state --state NEW -p tcp --dport 22 -m set --match-set my_local src -j ACCEPT
my_hostsからの全ての接続を許可する
-I INPUT -m set --match-set my_hosts src -j ACCEPT
書き方のポイント
-m set --match-set my_local src -j ACCEPT
-m set
Ipset モジュールを指定--match-set
セットにマッチする条件を指定my_local
ipset で指定したリストを指定src
ここではSRCにリストを適用すると条件を指定( src / dst / src,dst のいずれか)
設定はこんな感じでかけた。
iptablesを書いたら保存とリロード
iptablesの保存とリロードは別の記事や他の人がいっぱい書いてるのでそれを参考にする。
man について
詳しい使い方はiptables-extensions(8)の中にあるので、次のマニュアルでsetの章に書いてある。
man 8 iptables-extensions
ipset については次のように書いてあった
set このモジュールは ipsec(8) で定義できる IP 集合にマッチする。 [!] --match-set setname flag[,flag]... where flags are the comma separated list of src and/or dst specifications and there can be no more than six of them. Hence the command iptables -A FORWARD -m set --match-set test src,dst will match packets, for which (if the set type is ipportmap) the source address and destination port pair can be found in the specified set. If the set type of the specified set is single dimension (for example ipmap), then the command will match packets for which the source address can be found in the specified set. --return-nomatch If the --return-nomatch option is specified and the set type supports the nomatch flag, then the matching is reversed: a match with an element flagged with nomatch returns true, while a match with a plain element returns false. ! --update-counters If the --update-counters flag is negated, then the packet and byte counters of the matching element in the set won't be updated. Default the packet and byte counters are updated. ! --update-subcounters If the --update-subcounters flag is negated, then the packet and byte counters of the matching element in the member set of a list type of set won't be updated. Default the packet and byte counters are updated. [!] --packets-eq value If the packet is matched an element in the set, match only if the packet counter of the element matches the given value too. --packets-lt value If the packet is matched an element in the set, match only if the packet counter of the element is less than the given value as well. --packets-gt value If the packet is matched an element in the set, match only if the packet counter of the element is greater than the given value as well. [!] -bytes-eq value If the packet is matched an element in the set, match only if the byte counter of the element matches the given value too. --bytes-lt value If the packet is matched an element in the set, match only if the byte counter of the element is less than the given value as well. --bytes-gt value If the packet is matched an element in the set, match only if the byte counter of the element is greater than the given value as well. The packet and byte counters related options and flags are ignored when the set was defined without counter support. The option --match-set can be replaced by --set if that does not clash with an option of other extensions. Use of -m set requires that ipset kernel support is provided, which, for standard kernels, is the case since Linux 2.6.39.
hash:net hash:ip 以外に何があるの?
ipset help
パッと見た感じ、 net :ネットワークアドレス(範囲)や port ( ポート)や mac アドレスなども含められるようですね。
Supported set types: hash:mac 0 Initial revision hash:ip,mac 0 Initial revision hash:net,iface 6 skbinfo support hash:net,iface 0 Initial revision hash:net,port 7 skbinfo support hash:net,port,net 2 skbinfo support
iptableを書くとしんどい
iptablesをガチがきしてくのは、もちろんちゃんとやるときは意識して記述もしているしテストも実施している。 しかし、ぱぱっと記述を終えるには長すぎることあり、結局いつもコピペしている。
コピペだといつまでも成長しないので、できる限り、都度都度記述していくように切り替えて、記述に親しんでいきたい。
iptables関連のスクリプトはほんとみんな秘伝のタレになってるので、ちょっとそのままコピペで使うのはこわい。
そのまま実行するとIPアドレスが大量に列挙されて行数がとんでもないことになる。本当に辛い。
アドレス(と範囲)を列挙するなら ipsetつかったほうが楽。
今後拡大するネットワークと ipv6を控えて 秘伝のタレで運用するのは限界もありそうだよね。
まぁ、あれだnftablesに移行しろって事で。
arch見てたらこんな記述が
nftables は既存の iptables(ip-,ip6-)を置き換える netfilter のプロジェクトです。 カーネル 3.13 から nftables を使うことができます
関連資料
ssh をiptablesで国内限定にする(日本国外のIPから規制する) - それマグで!