それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

ipset と iptables で 楽チンなFW管理

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 を使うことができます

nftables - ArchWiki

関連資料

ssh をiptablesで国内限定にする(日本国外のIPから規制する) - それマグで!

再起動時にipsetをリストアさせる方法: ままれのblog

https://github.com/BroHui/systemd-ipset-service