LinuxにおけるIPフォワーディング
概要
LinuxにはIPパケットをフォワーディングする機能が具備されている。IPフォワーディングはあるネットワークから受け取ったパケットを別のネットワークに転送する技術である。言い換えると、2つのNICの間でパケットを転送する技術である。これにより、パケットが異なるネットワークの間を往き来できるようになる*1。
LinuxでIPフォワードを有効にするには、カーネルパラメータ net.ipv4.ip_forward
の値を1にする必要がある(設定方法は過去エントリを参照 カーネルパラメータの設定方法(CentOS 8) - Knのアウトプット)。
カーネルパラメータを設定した段階では2つのNIC間でパケットが転送できるようになっただけで、適切な通信が行われるようになったわけではない。実際にフォワーディングされるためにはルーティングテーブルを適切に設定する必要がある。
設定例
サーバーA、B、Cの3台があり、Bに対しフォワーディングの設定を行う。
Bは2つのネットワーク、192.168.0.0/24
と192.168.122.0/24
に所属している。
[root@nuc-centos8 ~]# ip a (略) 4: wlp0s20f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 0c:7a:15:da:07:37 brd ff:ff:ff:ff:ff:ff inet 192.168.0.14/24 brd 192.168.0.255 scope global dynamic noprefixroute wlp0s20f3 (略) 5: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 52:54:00:9c:81:ac brd ff:ff:ff:ff:ff:ff inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 (略)
サーバAは192.168.0.0/24
のみに所属している。
[root@virtualbox-centos7 ~]# ip a (略) 3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 08:00:27:08:35:9c brd ff:ff:ff:ff:ff:ff inet 192.168.0.92/24 brd 192.168.0.255 scope global noprefixroute enp0s8 (略)
サーバCは192.168.122.0/24
のみに所属している。
[root@kvm-centos8 ~]# ip a (略) 2: ens2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 52:54:00:34:01:09 brd ff:ff:ff:ff:ff:ff inet 192.168.122.100/24 brd 192.168.122.255 scope global noprefixroute ens2 (略)
サーバAからサーバCへpingを打つ。このときサーバBでIPフォワーディングが有効になっており、ルーティングテーブルが設定されていればpingは到達する。 なお、サーバAからサーバBにパケットが飛ぶようにするため、サーバAのデフォルトゲートウェイはサーバBのIPアドレスにしてある。
[root@virtualbox-centos7 ~]# nmcli con show enp0s8 (略) ipv4.addresses: 192.168.0.92/24 ipv4.gateway: 192.168.0.14 (略)
サーバBではすでにIPフォワーディングが有効( net.ipv4.ip_forward = 1
)で、ルーティングテーブルも設定済みである*2。
[root@nuc-centos8 ~]# sysctl -a | grep net.ipv4.ip.forward net.ipv4.ip_forward = 1 net.ipv4.ip_forward_update_priority = 1 net.ipv4.ip_forward_use_pmtu = 0 [root@nuc-centos8 ~]# ip r default via 192.168.0.1 dev wlp0s20f3 proto dhcp metric 600 192.168.0.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.0.100 metric 600 192.168.0.0/24 dev wlp0s20f3 proto kernel scope link src 192.168.0.14 metric 600 192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
サーバAからpingを打つ。応答が返ってきていることがわかる。
[root@virtualbox-centos7 ~]# ping 192.168.122.100 PING 192.168.122.100 (192.168.122.100) 56(84) bytes of data. 64 bytes from 192.168.122.100: icmp_seq=1 ttl=63 time=106 ms 64 bytes from 192.168.122.100: icmp_seq=2 ttl=63 time=22.9 ms 64 bytes from 192.168.122.100: icmp_seq=3 ttl=63 time=41.1 ms (略)
pingを打ちっぱなしのままサーバCでtcpdumpを使いパケットを監視してみると、ICMPのrequestが飛んできている。
[root@kvm-centos8 ~]# tcpdump -i any src host 192.168.0.92 -n tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 11:07:47.686403 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 57, length 64 11:07:48.710472 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 58, length 64 11:07:49.734488 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 59, length 64 11:07:50.656000 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2747, seq 60, length 64 (略)
pingとtcpdumpを仕掛けたまま、サーバB上でIPフォワーディングを無効化してみる。一時的に無効化するにはファイル/proc/sys/net/ipv4/ip_forward
の値を直接0に書き換える。
[root@nuc-centos8 ~]# echo 0 > /proc/sys/net/ipv4/ip_forward
サーバAのping応答が止まる。
(略) 64 bytes from 192.168.122.100: icmp_seq=126 ttl=63 time=98.5 ms 64 bytes from 192.168.122.100: icmp_seq=127 ttl=63 time=117 ms (ここで止まる)
サーバCでもtcpdumpの更新が止まる。
(略) 11:11:26.734165 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2748, seq 126, length 64 11:11:27.757086 IP 192.168.0.92 > 192.168.122.100: ICMP echo request, id 2748, seq 127, length 64 (ここで止まる)
サーバB上でIPフォワーディングを再び有効にするとpingの応答が返り、tcpdumpの更新が再開される(応答が返ってきている様子等は割愛する)。
[root@nuc-centos8 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
参考にしたもの
カーネルパラメータの設定方法(CentOS 8)
カーネルパラメータの設定箇所
世の中の記事では、net.ipv4.ip_forward
をはじめとしたカーネルパラメータは/etc/sysctl.conf
に記述するとあるが、ほかのファイルに分散されて書かれていることがある。
筆者の手元にある、CentOS 8では以下のように書かれていた。
[root@localhost ~]# cat /etc/sysctl.conf # sysctl settings are defined through files in # /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/. # # Vendors settings live in /usr/lib/sysctl.d/. # To override a whole file, create a new file with the same in # /etc/sysctl.d/ and put new settings there. To override # only specific settings, add a file with a lexically later # name in /etc/sysctl.d/ and put new settings there. # # For more information, see sysctl.conf(5) and sysctl.d(5).
To override a whole file, create a new file with the same in /etc/sysctl.d/ and put new settings there.
とあるので、/etc/sysctl.d
に自分がデフォルトから変えたいカーネルパラメータを記述したファイルを置くと思われる。
/etc/sysctl.d
を見てみる。99-sysctl.conf
というファイルのみが置かれているが、/etc/sysctl.conf
へのシンボリックリンクになっている。
[root@localhost ~]# ls -lhtra /etc/sysctl.d/99-sysctl.conf lrwxrwxrwx. 1 root root 14 Apr 23 2020 /etc/sysctl.d/99-sysctl.conf -> ../sysctl.conf
つまり、/etc/sysctl.conf
のファイルも含め、/etc/sysctl.d
配下に置かれたファイルがユーザ設定として上書きされる。
Vendors settings live in /usr/lib/sysctl.d/
とあるので、CentOSのディストリビューションに同梱されているアプリケーションの設定に関わるカーネルパラメータがここにあると想定される。
[root@localhost ~]# ls -lhtr /usr/lib/sysctl.d/ total 24K -rw-r--r--. 1 root root 246 May 11 2019 50-libkcapi-optmem_max.conf -rw-r--r--. 1 root root 636 Apr 23 2020 50-pid-max.conf -rw-r--r--. 1 root root 1.3K Apr 23 2020 50-default.conf -rw-r--r--. 1 root root 524 Apr 23 2020 50-coredump.conf -rw-r--r--. 1 root root 1.8K Apr 24 2020 10-default-yama-scope.conf -rw-r--r--. 1 root root 499 May 28 2020 60-libvirtd.conf
デフォルトでは/run/sysctl.d
は存在しなかった。
[root@localhost ~]# ls -lhtr /run/sysctl.d ls: cannot access '/run/sysctl.d': No such file or directory
設定例
試しにパケット転送を制御するカーネルパラメータであるnet.ipv4.ip_forward
を設定してみる。デフォルトではオフ(=0)になっている。なお、カーネルパラメータは<TUNABLE_CLASS>.<PARAMETER>=<TARGET_VALUE>
という形式になる。この例では<TUNABLE_CLASS>
はnet
とipv4
、<PARAMETER>
がip_forward
、<TARGET_VALUE>
が0か1、という具合である*1。
[root@localhost ~]# sysctl -a | grep net.ipv4.ip_forward net.ipv4.ip_forward = 0 net.ipv4.ip_forward_update_priority = 1 net.ipv4.ip_forward_use_pmtu = 0
/proc/sys/<TUNABLE_CLASS>/<PARAMETER>
にカーネルパラメータの<TARGET_VALUE>
のみが記載されたテキストファイルがあり*2、それでも確認可能*3。
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward 0
設定ファイルを作成し*4、設定を反映する。
[root@localhost ~]# echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/net.ipv4.ip_forward.conf [root@localhost ~]# cat /etc/sysctl.d/net.ipv4.ip_forward.conf net.ipv4.ip_forward = 1 [root@localhost ~]# sysctl -p /etc/sysctl.d/net.ipv4.ip_forward.conf net.ipv4.ip_forward = 1
設定が反映されている。
[root@localhost ~]# sysctl -a | grep net.ipv4.ip_forward net.ipv4.ip_forward = 1 net.ipv4.ip_forward_update_priority = 1 net.ipv4.ip_forward_use_pmtu = 0 [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward 1
ちなみに、再起動後も反映されている。
[root@localhost ~]# reboot (略) localhost login: root Password: Last login: Fri Jan 15 19:49:21 on ttyS0 [root@localhost ~]# sysctl -a | grep net.ipv4.ip_forward net.ipv4.ip_forward = 1 net.ipv4.ip_forward_update_priority = 1 net.ipv4.ip_forward_use_pmtu = 0 [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward 1
参考にしたもの
第5章 ランタイム時のカーネルパラメーターの設定 Red Hat Enterprise Linux 8 | Red Hat Customer Portal
SGIDを実行ファイルに設定した際の挙動
SGIDとは
SGID(Set Group ID)とは、実行権のあるファイルに設定される特殊なアクセス権の1つ。 実行ファイルにSGID(Set Group ID)が設定されている場合は、その実行ファイルを実行すると、実行ファイルの所有グループの権限でファイルが実行される。
知りたいこと
実行ファイルの所有グループの権限でファイルが実行されるとは具体的にはどういうことか?
Linuxのプロセスにおいては、実効グループIDというIDが設定される*1。通常はプロセスは、実行ファイルを実行したユーザの所有グループが実効グループIDになる。ここで、実行ファイルにSGIDというフラグを設定すると、実行ファイルの所有者がプロセスの実効グループIDになる。
動作検証
概要
phil
というユーザで検証用のプログラムを実行し、実行中のプロセスの実効グループIDを確認する。検証用のプログラムの所有グループはtestuser
である。
phil
の所有グループIDは1007である。
[phil@nuc-centos8 ~]$ id uid=1002(phil) gid=1007(accounting) groups=1007(accounting) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
testuser
の所有グループIDは1001である。
[testuser@nuc-centos8 test]$ id uid=1001(testuser) gid=1001(testuser) groups=1001(testuser),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
検証用プログラムの作成
簡単なC言語のプログラムを用意する。無限ループするだけのものである。
#include <stdio.h> int main() { printf("now executing\n"); while (1) { } }
コンパイルする。loop
という名前の実行ファイルができている。
[testuser@nuc-centos8 test]$ gcc loop.c -o loop [testuser@nuc-centos8 test]$ ls -lhtra total 20K -rw-rw-r--. 1 testuser testuser 123 Jan 13 07:33 loop.c drwxrwxrwx. 5 testuser testuser 144 Jan 13 07:33 .. drwxrwxr-x. 2 testuser testuser 32 Jan 13 07:33 . -rwxrwxr-x. 1 testuser testuser 13K Jan 13 07:33 loop
loop
をコピーしてloop-sgid
という実行ファイルを用意し、loop-sgid
にSGIDを設定する。見づらいが、パーミッションが-rwxrwxr-xから-rwxrwsr-xに変化している。
[testuser@nuc-centos8 test]$ cp loop loop-sgid [testuser@nuc-centos8 test]$ ls -lhtra total 36K -rw-rw-r--. 1 testuser testuser 93 Jan 13 07:48 loop.c drwxrwxrwx. 5 testuser testuser 144 Jan 13 07:48 .. drwxrwxr-x. 2 testuser testuser 49 Jan 13 07:48 . -rwxrwxr-x. 1 testuser testuser 13K Jan 13 07:48 loop -rwxrwxr-x. 1 testuser testuser 13K Jan 13 07:52 loop-sgid [testuser@nuc-centos8 test]$ sudo chmod g+s loop-sgid [testuser@nuc-centos8 test]$ ls -lhtra total 36K -rw-rw-r--. 1 testuser testuser 123 Jan 13 07:33 loop.c drwxrwxrwx. 5 testuser testuser 144 Jan 13 07:33 .. -rwxrwxr-x. 1 testuser testuser 13K Jan 13 07:33 loop drwxrwxr-x. 2 testuser testuser 49 Jan 13 07:35 . -rwxrwsr-x. 1 testuser testuser 13K Jan 13 07:35 loop-sgid
実効グループIDの確認
SGIDの設定されていないプログラム(loop)を実行した場合。このとき、phil
の所有グループ1007が実効グループIDになることが期待される。
[phil@nuc-centos8 test]$ ./loop now executing
別端末でプロセスIDを確認し、実効ユーザIDを出力する。期待通り、testuser
の所有グループのIDの1007で実行されている。
[root@nuc-centos8 ~]# top top - 08:18:21 up 16 days, 8:07, 4 users, load average: 0.38, 0.43, 0.28 Tasks: 237 total, 2 running, 235 sleeping, 0 stopped, 0 zombie %Cpu(s): 12.7 us, 0.0 sy, 0.0 ni, 87.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 31778.6 total, 30562.0 free, 471.7 used, 744.8 buff/cache MiB Swap: 16036.0 total, 16036.0 free, 0.0 used. 30888.3 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 280107 phil 20 0 4328 808 744 R 93.8 0.0 0:17.97 loop (略) [root@nuc-centos8 ~]# ps -o sgid 280107 SGID 1007
一方、SGIDを設定したプログラム(loop-sgid)を実行する。このとき、testuser
の所有グループ1001が実効グループIDになることが期待される。
[phil@nuc-centos8 test]$ ./loop-sgid now executing
期待通り、所有グループID 1001で実行されている。
[root@nuc-centos8 ~]# top top - 08:22:14 up 16 days, 8:11, 4 users, load average: 1.00, 0.75, 0.46 Tasks: 240 total, 3 running, 237 sleeping, 0 stopped, 0 zombie %Cpu(s): 12.9 us, 0.0 sy, 0.0 ni, 87.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st MiB Mem : 31778.6 total, 30561.7 free, 472.1 used, 744.8 buff/cache MiB Swap: 16036.0 total, 16036.0 free, 0.0 used. 30887.9 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 280140 phil 20 0 4328 688 624 R 93.8 0.0 1:17.09 loop-sgid (略) [root@nuc-centos8 ~]# ps -o sgid 280140 SGID 1001
今後の課題
実行中プロセスの所属グループ(Linux) - Qiita によると、/proc/プロセスID/status
のGroups
でもプロセスの所属グループが確認できるとのこと。
ところが、実行してみると、どうも実効グループIDを表していない様子。
SGIDを設定していないプログラムを実行した場合。
[root@nuc-centos8 ~]# cat /proc/280107/status | grep Group Groups: 1007
SGIDを設定したプログラムを実行した場合(実効グループIDを表すのであれば1001になっているはず)。
[root@nuc-centos8 ~]# cat /proc/280140/status | grep Group Groups: 1007
おそらく、ここは実グループIDのほうを設定していると予想されるだが、詳細を確認する時間がなくなったので今後の課題とする。
参考にしたもの
*1:実効ユーザIDもある。それに関する記事は多いのだが実効ユーザIDについて書かれているものが少ないので記事を書いた。また、実ユーザID、実グループIDもあり、これらも実効ユーザIDや実効グループIDとは別である
sar
sarとは
sar(System Admin Reporter)とはLinux上でのリソース情報を取得するツール(コマンド)で、sysstatパッケージの一部に含まれている。CPU、メモリ、ディスク、ネットワークに関する情報が取得できる。取得対象は実行時のオプションを指定することで変更することができる。本記事ではオプションや、実行時の各データの意味の詳細は割愛する。
使い方
コマンドによる一時的な実行
sar (取得対象を指定するオプション) 情報取得間隔 情報取得回数
を実行すればよい。以下は実行例である。取得対象を指定しなかったため、デフォルトのCPUに関する値が取得されている。
# sar 1 5 Linux 3.10.0-1127.el7.x86_64 (localhost.localdomain) 2020年10月02日 _x86_64_ (1 CPU) 07時14分02秒 CPU %user %nice %system %iowait %steal %idle 07時14分03秒 all 0.00 0.00 0.00 0.00 0.00 100.00 07時14分04秒 all 0.00 0.00 0.99 0.00 0.00 99.01 07時14分05秒 all 0.00 0.00 0.99 0.00 0.00 99.01 07時14分06秒 all 0.00 0.00 0.00 0.00 0.00 100.00 07時14分07秒 all 0.00 0.00 0.00 0.00 0.00 100.00 平均値: all 0.00 0.00 0.40 0.00 0.00 99.60
定期的なシステムの状態の保存
人がコマンドでsarを実行する以外に、sysstatとして定期的にシステム状態を保存する仕組みが用意されている。
sysstatにはsarのほかにsadcコマンドが含まれている。sarはsadcと連動して動作する。sadcはシステム状態をバイナリ形式で収集するコマンドで、sarはsadcが収集したバイナリデータをテキスト形式に変換する。sysstatパッケージにはsa1、sa2*1というスクリプトが用意されている。sa1はsadcコマンドの実行を行うもの、sa2はsarの実行を行うもので、スクリプト内では入出力ファイル等を定義している。sa1はsaXX(XXは日付)というファイルにバイナリデータを出力する。sa2はsaXXをsarXX(XXは日付)というテキストファイルに変換する。sa1とsa2の定期実行はcronに記載されている。デフォルトの実行設定はではsa1は10分ごと、sa2は1日1回である*2。
sadf
sarによって作られたテキストデータをCSV、XML等のフォーマットに整形するsadfというツールもある。システムのログ情報を機械可読性の高い形式にすることがsadfの1つの目的である。
参考にしたもの
障害の兆候を見逃さないためのサーバ監視 (2/3):Linux管理者への道(7) - @IT
ストレージ
ストレージとは
データを蓄積する入れ物のこと。具体的には文脈に応じて取る意味が異なる。IT*1の文脈に限っても以下の使い方がある。
- コンピュータ内の記憶装置(HDDやSDD等の補助記憶装置や、USBメモリ等の外部記憶装置)
- ストレージサーバのこと
ITシステムにはストレージは不可欠な存在であり、必ずストレージ機能を提供しているものがどこかにある。個々のシステムで「ストレージ」と言う言葉が何を指しているのかは利用している機器、ソフトウェア、アーキテクチャなどにより多岐にわたる*2。
ストレージサーバについて
ストレージサーバは、サーバの一種でストレージを機能として提供することを目的としている*3。ストレージを制御するソフトウェアがストレージサーバには搭載されている。
ストレージサーバもハードウェアと一体化しているものが多いが、ソフトウェアとして提供されており汎用のサーバ機器上にストレージソフトウェアをインストールして利用するものもある*4。
参考にしたもの
記憶領域ごとのレイテンシの目安
背景
以前の記事(コンピュータにおける記憶領域 - Knのアウトプット)で、コンピュータでの各記憶領域の入出力の速さを比較した。実際のスケール感をイメージしておくためメモする。
レイテンシのスケール感比較
レイテンシの目安を示したサイトがあったので(計算機の代表的なレイテンシとスケール感、Latency Numbers Every Programmer Should Know)、それを参考にまとめる*1。両サイトで数値にずれがある場合*2、両サイトの最大値と最小値を採用しその間に収まるものとする。カッコ内の何倍、というのはかなり端折った値にしている(規模をつかむのが重要なため)。
- CPUサイクル(基準):0.3ns*3
- キャッシュ:1ns~10数ns(基準の3倍~5倍程度、数クロック程度)*4
- メモリ:100ns~120ns(基準の30倍~40倍、キャッシュアクセスの10~100倍)
- SSD:16μs~150μs(基準の5×104倍~5×105倍、メモリアクセスの100倍~1000倍)
- HDD:1ms~10ms(基準の3×106~3×107倍、SSDの100倍~1000倍)
いろいろなケースをすごく乱暴に省略すると、CPUサイクルは1ns未満、キャッシュはその数倍、メモリはその100倍、SSDはその100倍、HDDはその100倍、というのが覚えやすい。
その他興味深い数値
Latency Numbers Every Programmer Should Know によると同一データのラウンドトリップタイムは500μs程度。
一方、第2回 ネットワーク遅延と高速化:教科書には載っていない ネットワークエンジニアの実践技術|gihyo.jp … 技術評論社によれば、東京~大阪でのネットワーク遅延が20ms程度が目安なので、当たり前だが同一マシン内のデータアクセスや同一データセンタ内のデータアクセスに比べれば低速である。ping値の測定方法と速度目安 どれくらいの速度ならOK? | フレッツ光ナビによると、オンラインゲームをするケースでは20msは超高速ではないが高速といった体感で、50msを超えると人間に遅延が体感されるらしい。
参考にしたもの
Numbers Every Programmer Should Know By Year
NetApp HCI -番外編- NetApp HCIの圧倒的ストレージパフォーマンスっ!!|技術ブログ|C&S ENGINEER VOICE
ping値の測定方法と速度目安 どれくらいの速度ならOK? | フレッツ光ナビ
第2回 ネットワーク遅延と高速化:教科書には載っていない ネットワークエンジニアの実践技術|gihyo.jp … 技術評論社