#0
podへのパケット転送に、iptablesのstatisticという拡張モジュールを使って
いるのがわかった。
statisticにprobability という機能があるようで、
kubernetesのservice宛てにパケット送ると、あるときはnode1のPod,
あるときは、node2のPod、というようにパケットを振り分けをすることが
できるようだ。
ようは、probability は、ロードバランサーが実サーバにパケットを振り分ける
のと同じようなことをしている。
serviceというリソースを作成するということは、statisticモジュールを使って、
パケットの振り分けルールをiptabelesに設定する、ということのようだ。
#1 はじめに
- そもそも、iptablesのことを知らない。基本から勉強
- Docker,Kubernetesがiptablesをどのように使っているか、さっぱりわからない。
- ということで、調べることにした。
#2 環境
[root@master1 ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
#3 用語の意味
-
チェインとは? ルールの集合であり、そのルールを実行する場所がOS内に5箇所ある。
-
PREROUTING
-
INPUT
-
OUTPUT
-
POSTROUTING
-
FORWARD
-
ルールとは? ある条件にマッチしたらパケットを廃棄する、といった規則のこと。
-
ユーザ定義チェインとは? たとえばC言語の関数のようなもの。
INPUTからユーザ定義チェインを呼び出す、というような使い方をする。
さらに、ユーザ定義チェインからユーザ定義チェインを呼び出すことも可能。
#4 iptablesの勉強
DockerやKubernetesは、独自のユーザ定義チェインを作成し、そのチェインにDNATを定義している。
まず、ユーザ定義チェインの作成、削除、ユーザ定義チェインへのルール追加、削除を実践してみる。
特にKubernetesは、ユーザ定義チェインを何段も呼び出す形で実装されており、初めて見ると、どの
ようなルールでパケットを廃棄したり許可しているのか見当がつかない。
##4.1 ルールの追加(-A)、表示(-L)、削除(-D)方法
テスト用にルールを2つ作成する。
宛先TCPポート番号5000,6000のパケットを受信したら廃棄、というルールをINPUT チェインに作成する。
[root@master1 ~]# iptables -A INPUT -p tcp --dport 5000 -j DROP
[root@master1 ~]# iptables -A INPUT -p tcp --dport 6000 -j DROP
作成したルールを確認する。
[root@master1 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5000
2 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6000
1番目のルールを削除する。
[root@master1 ~]# iptables -D INPUT 1
[root@master1 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:6000
1番目のルールを削除する。全てのルールが削除できたことがわかる。
[root@master1 ~]# iptables -D INPUT 1
[root@master1 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
##4.2 ユーザ定義チェインの作成(-N)、表示(-L)、削除(-X)方法
INPUT,OUTPUT等ような、初めからOSに組み込まれているデフォルトチェインの他に、
ユーザがチェインを定義して使うことができる。
ここでは、ユーザ定義チェインの作成(-N)、参照(-L)、削除(-X)を試してみる。
ユーザ定義チェインチェイン(HOGE)を確認する。未定義であることがわかる。
[root@master1 ~]# iptables -L HOGE
iptables: No chain/target/match by that name.
ユーザ定義チェインを作成する。
[root@master1 ~]# iptables -N HOGE
チェインを確認する。作成できたことがわかる。
[root@master1 ~]# iptables -L HOGE
Chain HOGE(0 references)
target prot opt source destination
ユーザ定義チェインを削除する。
[root@master1 ~]# iptables -X HOGE
チェインを確認する、削除できたことがわかる。
[root@master1 ~]# iptables -L HOGE
iptables: No chain/target/match by that name.
[root@master1 ~]#
##4.3 デフォルトチェイン(INPUT等)にユーザ定義チェインの追加、削除
INPUTチェインを確認する。まだ何も登録されていない。
[root@master1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ユーザ定義チェイン(HOGE)を作成する
[root@master1 ~]# iptables -N HOGE
作成したチェインを確認する。
[root@master1 ~]# iptables -L HOGE
Chain HOGE (0 references)
target prot opt source destination
INPUTチェインにユーザ定義チェインを追加する。
[root@master1 ~]# iptables -A INPUT -j HOGE
この時点で、INPUTとHOGEは以下のような関係になる。
------------------------------------------------------
INPUT
target prot opt source destination
+-- HOGE all -- anywhere anywhere
| ------------------------------------------------------
+-> HOGE
Chain HOGE (1 references) ★参照数が1になる。
target prot opt source destination
------------------------------------------------------
INPUTチェインにユーザ定義チェインが追加されたことがわかる。
[root@master1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
HOGE all -- anywhere anywhere
HOGEチェインを確認する。参照数が1になったことがわかる(INPUTチェインが参照しているため)
[root@master1 ~]# iptables -L HOGE
Chain HOGE (★1 references)
target prot opt source destination
INPUTチェインからユーザ定義チェインを削除する。
[root@master1 ~]# iptables -D INPUT -j HOGE
この時点で、INPUTとHOGEは以下のような関係になる。
------------------------------------------------------
INPUT
target prot opt source destination
------------------------------------------------------
HOGE
Chain HOGE (0 references) ★参照数が0になる。
target prot opt source destination
------------------------------------------------------
ユーザ定義チェインが削除されたことがわかる。
[root@master1 ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
参照数が0になったことがわかる。
[root@master1 ~]# iptables -L HOGE
Chain HOGE (★0 references)
target prot opt source destination
ユーザ定義チェインを削除する。
[root@master1 ~]# iptables -X HOGE
[root@master1 ~]# iptables -L HOGE
iptables: No chain/target/match by that name.
[root@master1 ~]#
この時点で、チェインは以下のようになる。HOGEは削除されてしまった。
------------------------------------------------------
INPUT
target prot opt source destination
------------------------------------------------------
##4.4 ターゲット(-j)の使い方
ここでは、LOGターゲットの使い方について調べる。
ルールにマッチしたらsyslogにログを出力する、というターゲットを作成する。
ICMPパケットを受信したらログに残すルールを追加。
[root@master1 ~]# iptables -A INPUT -p icmp -j LOG
追加したルールを確認する。
[root@master1 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 LOG icmp -- 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
自分自身にpingを実行すると、syslogにログが記録されたことがわかる。1行が長いので折り返しています。
[root@master1 ~]# tail -n 1 /var/log/messages
Jan 28 22:55:56 master1 kernel:
IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00
SRC=192.168.0.10
DST=192.168.0.10
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=28109 PROTO=ICMP TYPE=0 CODE=0 ID=6664 SEQ=1
ルールを削除する。
[root@master1 ~]# iptables -D INPUT 1
ルールの削除ができたことがわかる。
[root@master1 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
[root@master1 ~]#
##4.5 INPUTチェインにユーザ定義チェインとルールの追加
ユーザ定義チェイン(HOGE)を作成する。
[root@master1 ~]# iptables -N HOGE
ユーザ定義チェインにルールを追加する。
[root@master1 ~]# iptables -A HOGE -p icmp -j LOG
ユーザ定義チェインのルールを確認する。追加できたことがわかる。
[root@master1 ~]# iptables -L HOGE
Chain HOGE (0 references)
target prot opt source destination
LOG icmp -- anywhere anywhere LOG level warning
INPUTチェインにユーザ定義チェインを追加する。
[root@master1 ~]# iptables -A INPUT -j HOGE
INPUTチェインにルールを追加する。
[root@master1 ~]# iptables -A INPUT -p tcp --dport 10000 -j DROP
INPUTチェインのルールを確認する。
[root@master1 ~]# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
HOGE all -- 0.0.0.0/0 0.0.0.0/0
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:10000
ユーザ定義チェインのルールを確認する。
[root@master1 ~]# iptables -nL HOGE
Chain HOGE (1 references)
target prot opt source destination
LOG icmp -- 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
##4.6 DNATの使い方
master2側の80番ポートに到着したパケットを3000番ポートに転送する
-------------------
1. パケットの流れ
--------------------
ncプロセス(3000番ポート)
A
|
DNAT処理
|
80番ポート
A
|
master1 ---------> master2
-------------------
2. 事前準備
--------------------
nmap-ncatパッケージをmaster1,master2にインストールする。
[root@master1 ~]# yum -y install nmap-ncat
-以下、略
[root@master1 ~]# ncat --version
Ncat: Version 6.40 ( http://nmap.org/ncat )
-------------------
3. master2側の準備
--------------------
DNATテーブルをクリアする。
[root@master2 ~]# iptables -F -t nat
DNATテーブルがクリアされていることを確認する。
[root@master2 ~]# iptables -L -t nat -n|grep -e 80 -e 3000
DNAT処理(宛先ポート番号80を3000に変換)を登録する。
[root@master2 ~]# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 3000
DNATテーブルを確認する。
[root@master2 ~]# iptables -L -t nat -n|grep -e 80 -e 3000
REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 redir ports 3000
3000番ポートで待つ。
[root@master2 ~]# nc -lk -vv 3000 &
[1] 3375
[root@master2 ~]# Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::3000
Ncat: Listening on 0.0.0.0:3000
★リターンキーを入力
[root@master2 ~]# jobs
[1]+ 実行中 nc -lk -vv 3000 &
ポート番号3000を利用しているプロセスを確認する。ncコマンドを利用中であることがわかる。
[root@master2 ~]# lsof -i:3000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nc 3375 root 3u IPv6 36572 0t0 TCP *:hbci (LISTEN)
nc 3375 root 4u IPv4 36573 0t0 TCP *:hbci (LISTEN)
------------------------------
4. master1でTCPパケット送信する
-------------------------------
TCPパケット(宛先ポート番号80)をmaster2に送信する。応答がかえってきた。
[root@master1 ~]# nc -vv master2 80
Ncat: Version 6.40 ( http://nmap.org/ncat )
libnsock nsi_new2(): nsi_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to 192.168.0.20:80 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT SUCCESS for EID 8 [192.168.0.20:80]
Ncat: Connected to 192.168.0.20:80.
libnsock nsi_new2(): nsi_new (IOD #2)
libnsock nsock_read(): Read request from IOD #1 [192.168.0.20:80] (timeout: -1ms) EID 18
libnsock nsock_readbytes(): Read request for 0 bytes from IOD #2 [peer unspecified] EID 26
test ★適当な文字列を入力する。サーバ側にも同じ文字列が表示されることを確認する。
##4.7 デバッグ情報を表示する。(-vオプション)
-vオプションを指定すると、ルールにマッチしたパケット数、バイト数を表示できる。
ICMPパケットを受信したら、syslogにログを出力するルールを設定する。
[root@master2 ~]# iptables -A INPUT -p icmp -j LOG
別ターミナルをオープンする。まだ、pingは実行していない。
[root@master2 ~]# iptables -v -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT 54 packets, 11582 bytes)
num pkts bytes target prot opt in out source destination
1 ★0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
pingを1回実行した後の状態を確認する。pkts=1(★印)になっていることがわかる。
[root@master2 ~]# iptables -v -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT 70 packets, 28306 bytes)
num pkts bytes target prot opt in out source destination
1 ★1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
pingを2回実行した後の状態を確認する。pkts=2(★印)になっていることがわかる。
[root@master2 ~]# iptables -v -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT 9 packets, 8474 bytes)
num pkts bytes target prot opt in out source destination
1 ★2 168 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
[root@master2 ~]#
##4.8 NATを定義しているチェイン一覧の表示方法
bash-completionインストールしておくと便利。
-L入力のあと、TABキーを押下すると、チェイン一覧が表示される。
[root@master1 ~]# iptables -t nat -L
DOCKER KUBE-NODEPORTS KUBE-SERVICES POSTROUTING
INPUT KUBE-POSTROUTING KUBE-SVC-NPX46M4PTMTKRN6Y PREROUTING
KUBE-MARK-MASQ KUBE-SEP-JXR3GL4M4Y5HVZ4I OUTPUT
##4.9 定義済ルールの確認方法(-S)
Docker,Kubernetesが独自に定義したチェインがあることがわかる。
--------------
1. filter
--------------
[root@master1 ~]# iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION
-N KUBE-SERVICES
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A DOCKER-ISOLATION -j RETURN
--------------
2. nat
--------------
[root@master1 ~]# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-N KUBE-MARK-MASQ
-N KUBE-NODEPORTS
-N KUBE-POSTROUTING
-N KUBE-SEP-JXR3GL4M4Y5HVZ4I
-N KUBE-SERVICES
-N KUBE-SVC-NPX46M4PTMTKRN6Y
-A PREROUTING -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A KUBE-MARK-MASQ -j MARK --set-xmark 0x4000/0x4000
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
-A KUBE-SEP-JXR3GL4M4Y5HVZ4I -s 192.168.0.10/32 -m comment --comment "default/kubernetes:https" -j KUBE-MARK-MASQ
-A KUBE-SEP-JXR3GL4M4Y5HVZ4I -p tcp -m comment --comment "default/kubernetes:https" -m tcp -j DNAT --to-destination 192.168.0.10:6443
-A KUBE-SERVICES -d 10.254.0.1/32 -p tcp -m comment --comment "default/kubernetes:https cluster IP" -m tcp --dport 443 -j KUBE-SVC-NPX46M4PTMTKRN6Y
-A KUBE-SERVICES -m comment --comment "kubernetes service nodeports; NOTE: this must be the last rule in this chain" -m addrtype --dst-type LOCAL -j KUBE-NODEPORTS
-A KUBE-SVC-NPX46M4PTMTKRN6Y -m comment --comment "default/kubernetes:https" -j KUBE-SEP-JXR3GL4M4Y5HVZ4I
[root@master1 ~]#
--------------
3. mangle
--------------
[root@master1 ~]# iptables -t mangle -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
--------------
4. raw
--------------
[root@master1 ~]# iptables -t raw -S
-P PREROUTING ACCEPT
-P OUTPUT ACCEPT
##4.10 MARKターゲットの使い方
使い方のうちの1つとして、ルールをグループ化するときにMARKターゲットを使う。
以下の例では、宛先TCPポート番号が10000または20000のパケットを受信したときに
syslogにログを出力するが、個々にsyslogに出力するルールを書くのではなく、
syslogにログを出力するルールをMARKを使って1つにまとめている。
宛先TCPポート番号が10000と20000のパケットに"12"という印をつける。
[root@master2 ~]# iptables -A INPUT -p tcp --dport 10000 -j MARK --set-mark 12
[root@master2 ~]# iptables -A INPUT -p tcp --dport 20000 -j MARK --set-mark 12
INPUTチェインを確認する。
[root@master2 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 MARK tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:10000 MARK set 0xc
2 MARK tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:20000 MARK set 0xc
[root@master2 ~]#
"12"という印を付けたパケットを受信したときは、syslogにログを記録する。
[root@master2 ~]# iptables -A INPUT -m mark --mark 12 -j LOG
[root@master2 ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 MARK tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:10000 MARK set 0xc
2 MARK tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:20000 MARK set 0xc
3 LOG all -- 0.0.0.0/0 0.0.0.0/0 mark match 0xc LOG flags 0 level 4
syslogを確認する。
[root@master2 ~]# tail -f /var/log/messages
宛先TCPポート番号が10000(●印)のパケットを受信したときに出力されたログ。MARKが12(0xc)であることがわかる。
Jan 29 21:43:07 master2 kernel: IN=eth0
OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=49612 DF PROTO=TCP
SPT=32935 ●DPT=10000 WINDOW=29200 RES=0x00 SYN URGP=0 ★MARK=0xc
宛先TCPポート番号が20000(●印)のパケットを受信したときに出力されたログ。MARKが12(0xc)であることがわかる。
Jan 29 21:43:16 master2 kernel: IN=eth0
OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=15495 DF PROTO=TCP
SPT=37453 ●DPT=20000 WINDOW=29200 RES=0x00 SYN URGP=0 ★MARK=0xc
##4.11 MARKターゲットの使い方(その2)
PREROUTINGでマークを付けて、INPUTで指定したマークのパケットを廃棄する。
+------- master2 -------+
| +---------------+ |
| | nc | <===100番ポートで待ち受け
| +---- 1000 -----+ | nc -l master2 1000 -vv
| A |
| | |
| +---------------+ |
| | INPUT | <=== "5"の印が付いたパケットを廃棄する。
| +---------------+ |
| A |
| | |
| 自分宛て |
| | |
| +===============+ |
| | routing | ------- 他人宛て --->
| +---------------+ |
| | |
| | |
+-- master1 --+ | +---------------+ |
| | | | PREROUTING | <=== 宛先TCPポート番号10000のパケットに"5"の印をつける
+-------------+ | +---------------+ |
| | | |
| +-----------------------+
| A
| |
+---- 宛先ポート番号1000のTCPパケット -----+
-------------------
1. 事前準備
-------------------
master1,master2でncコマンドをインストールする。
[root@master1 ~]# yum -y install nmap-ncat
[root@master2 ~]# yum -y install nmap-ncat
------------------------------------
2. iptablesの設定(master2で実施する)
------------------------------------
ルールの設定 (宛先TCPポート番号1000のパケットに"5"という印をつける)
[root@master2 ~]# iptables -t nat -A PREROUTING -p tcp -dport 1000 -j MARK --set-mark 5
設定したルール(★印)を確認する。
[root@master2 ~]# iptables -t nat -nvL PREROUTING
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
19 2764 KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
12 720 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
★0 0 MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1000 MARK set 0x5
[root@master2 ~]#
ルールの設定 ("5"の印のパケットを受信したら廃棄)
[root@master2 ~]# iptables -A INPUT -m mark --mark 5 -j DROP
設定したルール(★印)を確認する。
[root@master2 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 17 packets, 1172 bytes)
pkts bytes target prot opt in out source destination
9568 11M all -- * * 0.0.0.0/0 0.0.0.0/0
8284 10M all -- * * 0.0.0.0/0 0.0.0.0/0
★0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x5
[root@master2 ~]#
-------------------
3. 確認作業
-------------------
master2でncコマンドを実行する。1000番ポートでパケット到着を待つ。
[root@master2 ~]# nc -l 1000 -vv
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Listening on :::1000
Ncat: Listening on 0.0.0.0:1000
このとき、master1でmaster2に向けて、宛先TCPポート番号1000のパケットを送信する。
しかし、ポート番号10000宛パケットを廃棄する設定にしているため、コネクションが確立できない。放置するとタイムアウトが発生する。
[root@master1 ~]# nc 192.168.0.20 1000 -vv
Ncat: Version 6.40 ( http://nmap.org/ncat )
libnsock nsi_new2(): nsi_new (IOD #1)
libnsock nsock_connect_tcp(): TCP connection requested to 192.168.0.20:1000 (IOD #1) EID 8
libnsock nsock_trace_handler_callback(): Callback: CONNECT TIMEOUT for EID 8 [192.168.0.20:1000]
Ncat: Connection timed out.
[root@master1 ~]#
PREROUTINGチェインを確認する。宛先TCPポート番号1000のパケットを4パケット受信して、印として"5"を付けた。
[root@master2 ~]# iptables -t nat -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 25 3410 KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
2 16 960 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
3 ★4 240 MARK tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:1000 MARK set 0x5
[root@master2 ~]#
印5のパケットを4パケット廃棄したことがわかる。
[root@master2 ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 21 packets, 9334 bytes)
num pkts bytes target prot opt in out source destination
1 10130 11M all -- * * 0.0.0.0/0 0.0.0.0/0
2 8846 11M all -- * * 0.0.0.0/0 0.0.0.0/0
3 ★4 240 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 mark match 0x5
-------------------
4. 後始末
-------------------
INPUTチェインからルールを削除する。
[root@master2 ~]# iptables -D INPUT 3
[root@master2 ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 7 packets, 504 bytes)
num pkts bytes target prot opt in out source destination
1 10281 11M all -- * * 0.0.0.0/0 0.0.0.0/0
2 8997 11M all -- * * 0.0.0.0/0 0.0.0.0/0
[root@master2 ~]#
PREROUTINGチェインからルールを削除する。
[root@master2 ~]# iptables -t nat -D PREROUTING 3
[root@master2 ~]# iptables -t nat -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 25 3410 KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
2 16 960 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
[root@master2 ~]#
##4.12 returnの使い方
###4.12.1 準備(LOGを使って、ログの出方を確認する)
ユーザ定義チェインを作成する。
[root@master2 ~]# iptables -N HOGE1
[root@master2 ~]# iptables -N HOGE2
[root@master2 ~]# iptables -N HOGE3
ユーザ定義チェインにルールを2つ作成する。
IMCPパケットを受信したらログを出力する、というルールを設定する。
[root@master2 ~]# iptables -A HOGE1 -p icmp -j LOG --log-prefix "HOGE11:"
[root@master2 ~]# iptables -A HOGE1 -p icmp -j LOG --log-prefix "HOGE12:"
[root@master2 ~]# iptables -A HOGE2 -p icmp -j LOG --log-prefix "HOGE21:"
[root@master2 ~]# iptables -A HOGE2 -p icmp -j LOG --log-prefix "HOGE22:"
[root@master2 ~]# iptables -A HOGE3 -p icmp -j LOG --log-prefix "HOGE31:"
[root@master2 ~]# iptables -A HOGE3 -p icmp -j LOG --log-prefix "HOGE32:"
設定したルールを確認する。
[root@master2 ~]# iptables -nvL HOGE1
Chain HOGE1 (0 references)
pkts bytes target prot opt in out source destination
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE11:"
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE12:"
設定したルールを確認する。
[root@master2 ~]# iptables -nvL HOGE2
Chain HOGE2 (0 references)
pkts bytes target prot opt in out source destination
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE21:"
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE22:"
設定したルールを確認する。
[root@master2 ~]# iptables -nvL HOGE3
Chain HOGE3 (0 references)
pkts bytes target prot opt in out source destination
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE31:"
0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE32:"
INPUTチェインにユーザ定義チェインを追加する。
[root@master2 ~]# iptables -A INPUT -j HOGE1
[root@master2 ~]# iptables -A INPUT -j HOGE2
[root@master2 ~]# iptables -A INPUT -j HOGE3
追加したユーザ定義チェインを確認する。
[root@master2 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 42 packets, 11597 bytes)
pkts bytes target prot opt in out source destination
62 20946 HOGE1 all -- * * 0.0.0.0/0 0.0.0.0/0
56 20322 HOGE2 all -- * * 0.0.0.0/0 0.0.0.0/0
42 11597 HOGE3 all -- * * 0.0.0.0/0 0.0.0.0/0
master1からmaster2にICMPパケットを1つ送信する。
[root@master1 ~]# ping -c 1 master2
ログを確認する。
[root@master2 ~]# tail -f /var/log/messages
Feb 7 19:57:29 master2 kernel: ★HOGE11:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5201 DF PROTO=ICMP TYPE=8 CODE=0 ID=2400 SEQ=1
Feb 7 19:57:29 master2 kernel: ★HOGE12:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5201 DF PROTO=ICMP TYPE=8 CODE=0 ID=2400 SEQ=1
Feb 7 19:57:29 master2 kernel: ★HOGE21:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5201 DF PROTO=ICMP TYPE=8 CODE=0 ID=2400 SEQ=1
Feb 7 19:57:29 master2 kernel: ★HOGE22:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5201 DF PROTO=ICMP TYPE=8 CODE=0 ID=2400 SEQ=1
Feb 7 19:57:29 master2 kernel: ★HOGE31:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5201 DF PROTO=ICMP TYPE=8 CODE=0 ID=2400 SEQ=1
Feb 7 19:57:29 master2 kernel: ★HOGE32:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5201 DF PROTO=ICMP TYPE=8 CODE=0 ID=2400 SEQ=1
-vをつけて、iptablesを実行する。ICMPパケットを受信したことがわかる。pktsの値が1に増えた。
[root@master2 ~]# iptables -nvL HOGE1
Chain HOGE1 (1 references)
pkts bytes target prot opt in out source destination
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE11:"
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE12:"
-vをつけて、iptablesを実行する。ICMPパケットを受信したことがわかる。pktsの値が1に増えた。
[root@master2 ~]# iptables -nvL HOGE2
Chain HOGE2 (1 references)
pkts bytes target prot opt in out source destination
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE21:"
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE22:"
-vをつけて、iptablesを実行する。ICMPパケットを受信したことがわかる。pktsの値が1に増えた。
[root@master2 ~]# iptables -nvL HOGE3
Chain HOGE3 (1 references)
pkts bytes target prot opt in out source destination
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE31:"
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE32:"
###4.12.2 最初のルールをreturnに変更する。
--------------
1. 実験概要
--------------
2の実験結果は、(1)->(2) ... ->(7)の順でルールが実行されることを示したものです。
rule2が実行されないことがわかる。
HOGE1
rule11 goto return (1)
rule12
HOGE2
rule21 (2)
rule22 (3)
HOGE3
rule31 (4)
rule32 (5)
--------------
2. 実験結果
--------------
HOGE1の最初のルールを書き換える。ICMPパケットを受信したらRETURNするように変更する。
[root@master2 ~]# iptables -R HOGE1 1 -p icmp -j RETURN
[root@master2 ~]# iptables -nvL HOGE1
Chain HOGE1 (1 references)
pkts bytes target prot opt in out source destination
0 0 RETURN★ icmp -- * * 0.0.0.0/0 0.0.0.0/0
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE12:"
master1からmaster2にICMPパケットを1つ送信する。
[root@master1 ~]# ping -c 1 master2
ログを確認する。HOGE1の2つのルールうち、最後のルールがスキップされたことがわかる。
[root@master2 ~]# tail -f /var/log/messages
Feb 7 20:06:00 master2 kernel: ★HOGE21:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5202 DF PROTO=ICMP TYPE=8 CODE=0 ID=2819 SEQ=1
Feb 7 20:06:00 master2 kernel: ★HOGE22:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5202 DF PROTO=ICMP TYPE=8 CODE=0 ID=2819 SEQ=1
Feb 7 20:06:00 master2 kernel: ★HOGE31:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5202 DF PROTO=ICMP TYPE=8 CODE=0 ID=2819 SEQ=1
Feb 7 20:06:00 master2 kernel: ★HOGE32:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5202 DF PROTO=ICMP TYPE=8 CODE=0 ID=2819 SEQ=1
##4.13 gotoの使い方
--------------
1. 実験概要
--------------
2の実験結果は、(1)->(2) ... ->(7)の順でルールが実行されることを示したものです。
rule2が実行されないことがわかる。さらに、HOGE3が2回実行されていることがわかる。
HOGE1
rule11 goto HOGE3 (1)
rule12
HOGE2
rule21 (4)
rule22 (5)
HOGE3
rule31 (2) (6)
rule32 (3) (7)
--------------
2. 実験結果
--------------
前述のルールから、HOGE1の最初のルールを以下のように書き換える。
[root@master2 ~]# iptables -R HOGE1 1 -p icmp --goto HOGE3
HOGE1のルールを確認する。
[root@master2 ~]# iptables -nvL HOGE1
Chain HOGE1 (1 references)
pkts bytes target prot opt in out source destination
0 0 HOGE3 icmp -- * * 0.0.0.0/0 0.0.0.0/0 [goto]
1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE12:"
HOGE2のルールを確認する。
[root@master2 ~]# iptables -nvL HOGE2
Chain HOGE2 (1 references)
pkts bytes target prot opt in out source destination
2 168 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE21:"
2 168 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE22:"
HOGE3のルールを確認する。
[root@master2 ~]# iptables -nvL HOGE3
Chain HOGE3 (2 references)
pkts bytes target prot opt in out source destination
2 168 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE31:"
2 168 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4 prefix "HOGE32:"
INPUTのルールを確認する。
[root@master2 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 50 packets, 27167 bytes)
pkts bytes target prot opt in out source destination
1358 1031K HOGE1 all -- * * 0.0.0.0/0 0.0.0.0/0
1352 1030K HOGE2 all -- * * 0.0.0.0/0 0.0.0.0/0
1338 1021K HOGE3 all -- * * 0.0.0.0/0 0.0.0.0/0
master1からmaster2にICMPパケットを1つ送信する。
[root@master1 ~]# ping -c 1 master2
[root@master2 ~]# tail -f /var/log/messages
Feb 7 20:18:40 master2 kernel: ★HOGE31:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5203 DF PROTO=ICMP TYPE=8 CODE=0 ID=3388 SEQ=1
Feb 7 20:18:40 master2 kernel: ★HOGE32:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5203 DF PROTO=ICMP TYPE=8 CODE=0 ID=3388 SEQ=1
Feb 7 20:18:40 master2 kernel: ★HOGE21:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5203 DF PROTO=ICMP TYPE=8 CODE=0 ID=3388 SEQ=1
Feb 7 20:18:40 master2 kernel: ★HOGE22:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5203 DF PROTO=ICMP TYPE=8 CODE=0 ID=3388 SEQ=1
Feb 7 20:18:40 master2 kernel: ★HOGE31:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5203 DF PROTO=ICMP TYPE=8 CODE=0 ID=3388 SEQ=1
Feb 7 20:18:40 master2 kernel: ★HOGE32:IN=eth0 OUT= MAC=00:0c:29:a5:64:c8:00:0c:29:18:5c:90:08:00
SRC=192.168.0.10
DST=192.168.0.20
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=5203 DF PROTO=ICMP TYPE=8 CODE=0 ID=3388 SEQ=1
##4.14 TCPフラグの指定方法(--tcp-flags)
特定のTCPフラグがたったTCPパケットの指定方法を以下に示す。
TCP フラグが指定されたものと等しい場合にマッチする。
-
第1引き数 : 評価対象とするフラグで、コンマ区切りのリストである。
-
第2引き数 : このうち設定されていなければならないフラグで、 コンマ区切りのリストである。
指定できるフラグは "SYN ACK FIN RST URG PSH ALL NONE" である。--tcp-flags <第1引数> <第2引数>
初期状態のルールを確認する。
[root@node1 ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
SYNパケット(宛先ポート番号11111)を廃棄するルールを設定する。
[root@node1 ~]# iptables -I INPUT -p tcp --dport 11111 --tcp-flags ALL SYN -j DROP
ルールを確認する(ポート番号等を数値に変換した状態で確認する)。
[root@node1 ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 42 packets, 4176 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 DROP tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111 flags:0x3F/0x02
ルールを確認する(ポート番号等を数値に変換しない)。
[root@node1 ~]# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- anywhere anywhere tcp dpt:vce flags:FIN,SYN,RST,PSH,ACK,URG/SYN
ルールを削除する。
[root@node1 ~]# iptables -D INPUT 1
[root@node1 ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 5 packets, 488 bytes)
num pkts bytes target prot opt in out source destination
##4.15 複数ポートの指定方法
INPUTチェインの初期状態を確認する。何も登録されていないことがわかる。
[root@admin ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 61 packets, 7120 bytes)
num pkts bytes target prot opt in out source destination
宛先TCPポート番号が10000-10005のパケットの受信を許可する。
[root@admin ~]# iptables -A INPUT -i eth0 -m multiport -p tcp --dports 10000:10005 -j ACCEPT
INPUTチェインを確認する。受信許可の設定ができたことがわかる(★印)。
[root@admin ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 13 packets, 1288 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 ★multiport dports 10000:10005
設定したルールを削除する。
[root@admin ~]# iptables -D INPUT 1
INPUTチェインを確認する。設定したルールが削除できたことがわかる。
[root@admin ~]# iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 5 packets, 488 bytes)
num pkts bytes target prot opt in out source destination
##4.16 任意の場所にルールを挿入する方法(-I)
-Iオプションを使うと、任意の位置にルールを挿入することができます。
(-Iオプションで指定した位置(num)の前にルールを挿入する)
INPUTチェインの初期状態を確認する。
[root@server ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
5 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
ルールを挿入する。num=1の前にルールを挿入する。
[root@server ~]# iptables -I INPUT 1 -p tcp --dport 11111 -j DROP
ルールを確認する。旧1番(●)の前にルールが挿入できたことがわかる。
[root@server ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1★ DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111
2● ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
6 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
ルールを挿入する。num=3の前にルールを挿入する。
[root@server ~]# iptables -I INPUT 3 -p tcp --dport 22222 -j DROP
ルールを確認する。旧3番(●)の前にルールが挿入できたことがわかる。
[root@server ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3★ DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22222
4● ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
6 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
7 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
ルールを挿入する。num=6の前にルールを挿入する。
[root@server ~]# iptables -I INPUT 6 -p tcp --dport 33333 -j DROP
ルールを確認する。旧6番(●)の前にルールが挿入できたことがわかる。
[root@server ~]# iptables -nL INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:11111
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22222
4 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
6★ DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:33333
7● ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
8 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
#6. Dockerの場合
DockerもKubernetesも、ユーザ定義チェインを作成し、そのチェインにNATを定義をしている。
KubernetesのほうがDockerのユーザ定義チェインより複雑な構成になっている。
------------------------------------
1. ホストの外からコンテナに行く場合
------------------------------------
コンテナ起動前のiptablesの設定を保存する。
[root@master1 iptables]# iptables -S > before
コンテナを起動する。
[root@master1 iptables]# docker run -d -p 10000:80 nginx
a00dbe60f6a9c23200420caf5ad515102cfe7d74e8672115b19a4ccf26d40852
コンテナの状態を確認する。
[root@master1 iptables]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a00dbe60f6a9 nginx "nginx -g 'daemon off" 7 seconds ago Up 3 seconds 443/tcp, 0.0.0.0:10000->80/tcp boring_gates
[root@master1 iptables]#
コンテナ起動後のiptablesの設定を保存する。
[root@master1 iptables]# iptables -S > after
コンテナ起動前後のiptablesの設定の差分を確認する。
コンテナを起動すると、DOCKERというユーザ定義チェインが新規作成されることがわかる。
[root@master1 iptables]# diff -Nur before after
--- before 2017-02-04 10:24:19.389487914 +0900
+++ after 2017-02-04 10:25:06.381464426 +0900
@@ -48,6 +48,7 @@
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -m comment --comment "kubernetes service portals" -j KUBE-SERVICES
-A OUTPUT -j OUTPUT_direct
+-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
-A FORWARD_IN_ZONES -i eth0 -g FWDI_public
-A FORWARD_IN_ZONES -g FWDI_public
[root@master1 iptables]#
ユーザ定義チェイン(DOCKER)のルールを確認する。新規ルール(★印)が追加されたことがわかる。
[root@master1 iptables]# iptables -t nat -nvL DOCKER --line-numbers
Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
2★ 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:10000 to:172.17.0.2:80
[root@master1 iptables]#
もう1つコンテナを起動する。
[root@master1 iptables]# docker run -d -p 20000:80 nginx
1c74d82f2caf33576bf1dee3fa716069b55c831d2ee98c1df450fbe71d49a527
コンテナの状態を確認する。
[root@master1 iptables]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c74d82f2caf nginx "nginx -g 'daemon off" 5 seconds ago Up 2 seconds 443/tcp, 0.0.0.0:20000->80/tcp elated_jennings
a00dbe60f6a9 nginx "nginx -g 'daemon off" 5 minutes ago Up 5 minutes 443/tcp, 0.0.0.0:10000->80/tcp boring_gates
[root@master1 iptables]#
ユーザ定義チェイン(DOCKER)のルールを確認する。新規ルール(★印)が追加されたことがわかる。
eth0に到着したパケットは、以下のルールが適用される。
宛先TCP番号が10000のパケット ===> 宛先IPアドレスは172.17.0.2に変換。宛先ポート番号は80に変換。
宛先TCP番号が20000のパケット ===> 宛先IPアドレスは172.17.0.3に変換。宛先ポート番号は80に変換。
[root@master1 iptables]# iptables -t nat -nvL DOCKER --line-numbers
Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
2 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:10000 to:172.17.0.2:80
3★ 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:20000 to:172.17.0.3:80
[root@master1 iptables]#
ルーティングテーブルを確認する。
ルーティングテーブルを検索した結果、
宛先IPアドレスが172.17.0.2や172.17.0.3のパケットは、docker0ブリッジ(★印)から送信される。
[root@master1 iptables]# ip route show
default via 192.168.0.1 dev eth0 proto static metric 100
★172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.10 metric 100
コンテナにアクセスする。
root@master1 iptables]# curl http://192.168.0.10:10000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
-以下、略
コンテナにアクセスする。
[root@master1 iptables]# curl http://192.168.0.10:20000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
-以下、略
-------------------------------------------
2. コンテナからホストの外へいく場合(1の帰り)
-------------------------------------------
[root@master1 iptables]# iptables -t nat -nL POSTROUTING --line-numbers
Chain POSTROUTING (policy ACCEPT)
num target prot opt source destination
1 MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
2 KUBE-POSTROUTING all -- 0.0.0.0/0 0.0.0.0/0 /* kubernetes postrouting rules */
3 POSTROUTING_direct all -- 0.0.0.0/0 0.0.0.0/0
4 POSTROUTING_ZONES_SOURCE all -- 0.0.0.0/0 0.0.0.0/0
5 POSTROUTING_ZONES all -- 0.0.0.0/0 0.0.0.0/0
6 ★MASQUERADE tcp -- 172.17.0.2 172.17.0.2 tcp dpt:80
7 ★MASQUERADE tcp -- 172.17.0.3 172.17.0.3 tcp dpt:80
#7 コネクショントラッキング
特定コネクションのトラッキング情報を表示しないようにするための方法を以下に示します。
特定のトラッキング情報を表示しないようにするために、NOTRACKターゲットを使います。
##7.1 環境
仮想マシン2台構成です。client,serverはホスト名です。
client ------------------------------ server
192.168.0.110 192.168.0.100
##7.2 デフォルト動作の確認
serverでfirewalldが動作していることを確認する。
[root@server ~]# systemctl is-active firewalld.service
active
serverでconntrackコマンドを実行する。ICMPパケットのコネクショントラッキング情報だけを表示するようにする。
[root@server ~]# conntrack -E -p icmp
serverに対して,ICMPパケットを1つだけ送信する。pingコマンドでも良いですが、ここではhping3 コマンドを使います。
[root@client ~]# hping3 -I eth0 -c 1 -C 8 server
ICMPパケットを受信すると、コネクショントラッキングの情報が表示されることがわかります。
もしくは、/proc/net/nf_conntrackの中身を確認しても良いです。
[root@server ~]# conntrack -E -p icmp
[NEW] icmp 1 30 src=192.168.0.110 dst=192.168.0.100 type=8 code=0 id=1302 [UNREPLIED] src=192.168.0.100 dst=192.168.0.110 type=0 code=0 id=1302
[UPDATE] icmp 1 30 src=192.168.0.110 dst=192.168.0.100 type=8 code=0 id=1302 src=192.168.0.100 dst=192.168.0.110 type=0 code=0 id=1302
##7.3 NOTRACKターゲットの追加、削除の方法
送信元IPが192.168.0.110,送信先IPが192.168.0.100のICMPパケットは、コネクショントラッキングの対象外に設定する。
[root@server ~]# iptables -t raw -A PREROUTING -p icmp -s 192.168.0.110 -d 192.168.0.100 -j NOTRACK
設定を確認する。ICMPパケット(送信元IPが192.168.0.110,送信先IPが192.168.0.100)がコネクショントラッキングの対象外に設定されたことがわかる(★)。
[root@server ~]# iptables -t raw -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 65 packets, 7472 bytes)
num pkts bytes target prot opt in out source destination
1 303 32164 PREROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2★ 0 0 CT icmp -- * * 192.168.0.110 192.168.0.100 NOTRACK
設定を削除する。num=2を指定してPREROUTINGチェインより設定を削除する。
[root@server ~]# iptables -t raw -D PREROUTING 2
設定を確認する。設定が削除できたことがわかる。
[root@server ~]# iptables -t raw -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 5 packets, 488 bytes)
num pkts bytes target prot opt in out source destination
1 345 35964 PREROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
##7.4 NOTRACKターゲットを指定したときの実行例
送信元IPが192.168.0.110,送信先IPが192.168.0.100のICMPパケットは、コネクショントラッキングの対象外に設定する。
[root@server ~]# iptables -t raw -A PREROUTING -p icmp -s 192.168.0.110 -d 192.168.0.100 -j NOTRACK
設定を確認する。指定したICMPパケットがコネクショントラッキングの対象外に設定されたことがわかる(★)。
[root@server ~]# iptables -t raw -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 8 packets, 704 bytes)
num pkts bytes target prot opt in out source destination
1 403 40972 PREROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2★ 0 0 CT icmp -- * * 192.168.0.110 192.168.0.100 NOTRACK
conntrackコマンドを実行する。
[root@server ~]# conntrack -E -p icmp
serverに対してpingを実行する。ICMPパケットを1つだけ送信する。
[root@client ~]# hping3 -I eth0 -c 1 -C 8 server
ICMPパケットはコネクショントラッキングの対象外に設定したので、conntrackコマンドを実行しても何も表示されないことがわかる。
[root@server ~]# conntrack -E -p icmp
また、iptablesコマンドを実行すると、コネクショントラッキング対象外のICMPパケットを1つ(★)受信したことがわかる。
[root@server ~]# iptables -t raw -nvL PREROUTING --line-numbers
Chain PREROUTING (policy ACCEPT 59 packets, 5560 bytes)
num pkts bytes target prot opt in out source destination
1 454 45828 PREROUTING_direct all -- * * 0.0.0.0/0 0.0.0.0/0
2 ★1 168 CT icmp -- * * 192.168.0.110 192.168.0.100 NOTRACK
ICMPパケットを送信する。ただし、送信元IPアドレスを設定とは異なる(1.1.1.1)ものを指定する。
[root@client ~]# hping3 -I eth0 -c 1 -a 1.1.1.1 -C 8 server
送信元IPが1.1.1.1はコネクショントラッキング対象なので、下記のようにconntrack コマンドを実行すると、
コネクショントラッキング情報が表示されていることがわかる。
[root@server ~]# conntrack -E -p icmp
[NEW] icmp 1 30 src=1.1.1.1 dst=192.168.0.100 type=8 code=0 id=32005 [UNREPLIED] src=192.168.0.100 dst=1.1.1.1 type=0 code=0 id=32005
[UPDATE] icmp 1 30 src=1.1.1.1 dst=192.168.0.100 type=8 code=0 id=32005 src=192.168.0.100 dst=1.1.1.1 type=0 code=0 id=32005
hping3コマンドの使い方はここを参照ください。
#8 その他
##8.1 インタフェースの指定方法
###8.1.1 入力インタフェース(-i)の指定方法
eth1から受信するICMPパケットをログに記録する。
[root@router2 ~]# iptables -I INPUT -i eth1 -p icmp -j LOG
INPUTチェインを確認する。
[root@router2 ~]# iptables -nvL INPUT
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG icmp -- eth1 * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
-以下、略-
ログを確認する。eth1からICMPパケットを受信していることが確認できる。
[root@router2 ~]# journalctl -b0 -f
1月 13 16:54:08 router2 kernel: ★IN=eth1 OUT= MAC=00:0c:29:d4:53:32:00:0c:29:cb:56:8d:08:00 SRC=192.168.110.10 DST=192.168.200.20 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=18447 DF PROTO=ICMP TYPE=8 CODE=0 ID=1394 SEQ=1
###8.1.2 出力インタフェース(-o)の指定方法
eth1から送信するICMPパケットをログに記録する。
[root@router2 ~]# iptables -I OUTPUT -o eth1 -p icmp -j LOG
[root@router2 ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 21 packets, 2888 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG icmp -- * eth1 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
-以下、略-
ログを確認する。eth1からICMPパケットが送信されていることが確認できる。
[root@router2 ~]# journalctl -b0 -f
1月 13 17:00:28 router2 kernel: ★IN= OUT=eth1 SRC=192.168.200.20 DST=192.168.110.10 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=57557 PROTO=ICMP TYPE=0 CODE=0 ID=1398 SEQ=1
##8.2 プロトコルの指定方法(-p)
プロトコルとして、icmp,tcp,udp等キーワードを指定することができます。
/etc/protocolsに登録されているプロトコルが、キーワードとして使うことができるようです。
UDPパケットを送信したらログに出力する、というルールをOUTPUTチェインに追加する。
[root@router1 ~]# iptables -I OUTPUT -p udp -j LOG
OUTPUTチェインを確認する。
[root@router1 ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 3 packets, 456 bytes)
pkts bytes target prot opt in out source destination
0 0 LOG ★udp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
1141 191K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
NTPサーバの名前解決を行う。このとき、UDPパケットが送信される。
[root@router1 ~]# dig ntp.nict.jp +short
133.243.238.164
133.243.238.244
133.243.238.163
133.243.238.243
OUTPUTチェインを確認する。UDPパケットが1個送信されたことがわかる。
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 64 packets, 9692 bytes)
num pkts bytes target prot opt in out source destination
1 1 68 LOG ★udp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
2 1067 180K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
ルールを削除する。
[root@router1 ~]# iptables -D OUTPUT 1
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 4 packets, 624 bytes)
num pkts bytes target prot opt in out source destination
1 1118 188K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
##8.3 送信元IP/送信先IPを指定する方法(-s,-d)
ここでは、送信元IPを指定した例を説明します。
送信元IP(-s)が192.168.0.10のICMPパケットを送信したらログに出力する、というルールをOUTPUTチェインに設定する。
[root@router1 ~]# iptables -I OUTPUT -p icmp -s 192.168.0.10 -j LOG
OUTPUTチェインを確認する。ルールが追加されたことがわかる。
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 77 packets, 10840 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG icmp -- * * ★192.168.0.10 0.0.0.0/0 LOG flags 0 level 4
2 1573 240K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
デフォルトGWに対してpingを実行する。
[root@router1 ~]# ping -c 1 192.168.0.1
OUTPUTチェインを確認する。送信元IPが192.168.0.10のICMPパケットが1つ送信されたことがわかる。
[root@router1 ~]# iptables -nvL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 118 packets, 17424 bytes)
num pkts bytes target prot opt in out source destination
1 1 84 LOG icmp -- * * ★192.168.0.10 0.0.0.0/0 LOG flags 0 level 4
2 1614 246K OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
ルールを削除する
[root@router1 ~]# iptables -D OUTPUT 1
##8.4 送信元ポート番号/送信先ポート番号を指定する方法(--sport,--dport)
ここでは、送信先ポート番号を指定した例を説明します。
送信先ポート番号が53のUDPパケットを送信したらログに出力する、というルールをOUTPUTチェインに設定する。
[root@router1 ~]# iptables -I OUTPUT -p udp --dport 53 -j LOG
OUTPUTチェインを確認する。ルールが追加されたことがわかる。
[root@router1 ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 30 packets, 3920 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:★53 LOG flags 0 level 4
2 100 12640 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
NTPサーバの名前解決を行う。このとき、UDPパケットが送信される。
[root@router1 ~]# dig ntp.nict.jp +short
133.243.238.243
133.243.238.163
133.243.238.164
133.243.238.244
OUTPUTチェインを確認する。送信先ポート番号が53のUDPパケットが2つ送信されたことがわかる。
[root@router1 ~]# iptables -nvxL OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT 52 packets, 7592 bytes)
num pkts bytes target prot opt in out source destination
1 ★2 136 LOG udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 LOG flags 0 level 4
2 122 16312 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
ルールを削除する
[root@router1 ~]# iptables -D OUTPUT 1
##8.5 カウンタをクリアする方法(-Z)
ICMPパケットを送信したらログに記録する、というルールをOUTPUTチェインに設定する。
[root@router1 ~]# iptables -I OUTPUT -p icmp -j LOG
OUTPUTチェインを確認する。ルールが追加されたことがわかる。まだカウンタは0(★)であることがわかる。
[root@router1 ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 20 packets, 2752 bytes)
pkts bytes target prot opt in out source destination
★0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
139 18820 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
デフォルトGWに対してpingを実行する。
[root@router1 ~]# ping -c 1 192.168.0.1
ICMPパケットが1つ(★)送信されたことがわかる。
[root@router1 ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 54 packets, 8076 bytes)
pkts bytes target prot opt in out source destination
★1 84 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
173 24144 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
カウンタをクリアする。送信したICMPパケット数が0(★)にリセットされたことがわかる。
[root@router1 ~]# iptables -Z
[root@router1 ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 4 packets, 592 bytes)
pkts bytes target prot opt in out source destination
★0 0 LOG icmp -- * * 0.0.0.0/0 0.0.0.0/0 LOG flags 0 level 4
4 592 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
[root@router1 ~]# iptables -D OUTPUT 1
[root@router1 ~]# iptables -nvL OUTPUT
Chain OUTPUT (policy ACCEPT 5 packets, 648 bytes)
pkts bytes target prot opt in out source destination
34 4880 OUTPUT_direct all -- * * 0.0.0.0/0 0.0.0.0/0
##8.6 ルールを置き換える方法(-R)
OUTPUTチェインにルールを設定する。
[root@router1 ~]# iptables -A OUTPUT -p icmp -j LOG
OUTPUTチェインに設定したルールを確認する。
[root@router1 ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
2 LOG ★icmp -- anywhere anywhere LOG level warning
ICMPのルールからUDPのルールに置き換える。
[root@router1 ~]# iptables -R OUTPUT 2 -p udp -j LOG
[root@router1 ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
2 LOG ★udp -- anywhere anywhere LOG level warning
UDPのルールからTCPのルールに置き換える。
[root@router1 ~]# iptables -R OUTPUT 2 -p tcp -j LOG
[root@router1 ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
2 LOG ★tcp -- anywhere anywhere LOG level warning
OUTPUTチェインに設定したルールを削除する。
[root@router1 ~]# iptables -D OUTPUT 2
[root@router1 ~]# iptables -L OUTPUT --line-numbers
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
1 OUTPUT_direct all -- anywhere anywhere
#X. 参考情報
Dockerのネットワークを理解するために覚えたことまとめ
natテーブルを利用したLinuxルータの作成
とみぞーノート