今さらながらiptables基本（その４）：Ubuntu NAT環境下でForward（１）

# UbuntuのNAT環境下でForward
UbuntuのNAT環境下で、iptablesを用いてパケットの転送を行ったときのメモ。

## ネットワーク
![1_2_topology.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/8fe8e63c-450b-2b8e-319a-2830a87316c2.png)
iptablesを用いてLubuntuにNAT環境を構築。左がNAT外側（172.16.1.0/24）、右がNAT内側（192.168.1.0/24）である。末端のPCはすべて、Buster dogというLinux VMである。以降、Lubuntuの設定や実行状況を記載。

## 0. 転送設定
まずは、下記転送設定が必要。
```
$ sudo sysctl -w net.ipv4.ip_forward=1
```

## 1. IP Forward
ここでいう”IP Forward”は、”1 by 1 Static NAT”のようなもの。上記ネットワークにて、NAT外側IPアドレスである”172.16.1.254”をNAT内側IPアドレス”192.168.1.11 (Bdog2)”に対応させる（転送する）。

### 設定
Static NATの転送設定。
```
$ sudo iptables -t nat -A PREROUTING -i enp0s3 -j DNAT --to-destination 192.168.1.11
```
この設定だけでは、上記のNAT内側のBdog3からNAT外側Bdog1への通信ができてしまう。そこで、
```
$ sudo iptables -P FORWARD DROP
$ sudo iptables -A FORWARD -s 192.168.1.11 -j ACCEPT
$ sudo iptables -A FORWARD -i enp0s3 -j ACCEPT
```
により、FORWARDフィルターを用いて、”192.168.1.11 (Bdog2)”のみ通信できるよう設定する。最終的な設定状況は下記。
```
$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       all  --  anywhere             anywhere             to:192.168.1.11

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination  

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
ACCEPT     all  --  192.168.1.11         anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
```

### 検証
”172.16.1.11 (Bdog1)”から、LubuntuのNAT外側IPアドレス”172.16.1.254”へのpingを実行。
```
$ ping -c 3 172.16.1.254
PING 172.16.1.254 (172.16.1.254) 56(84) bytes of data.
64 bytes from 172.16.1.254: icmp_seq=1 ttl=63 time=3.02 ms
64 bytes from 172.16.1.254: icmp_seq=2 ttl=63 time=1.22 ms
64 bytes from 172.16.1.254: icmp_seq=3 ttl=63 time=1.18 ms

--- 172.16.1.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 4ms
rtt min/avg/max/mdev = 1.184/1.808/3.018/0.855 ms
```
Wiresharkで取得したNAT外側の状況は下記となる。
![1_outside.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/23a72ca7-77b6-225e-c60f-02ebf61fd5ef.png)
当然であるが、”172.16.1.11 (Bdog1)”と”172.16.1.254 (Lubuntu NAT外側)”とが見える。NAT内側の状況は下記となる。
![1_inside.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/94076bfb-56d1-1349-fc98-e37665240156.png)
”172.16.1.11 (Bdog1)”と”192.168.1.11 (Bdog2)”とが見え、”172.16.1.254 (Lubuntu NAT外側)”が”192.168.1.11 (Bdog2)”に変換されていることがわかる。

## 2. Port Forward
ここでは、NAT外側のTCPポート60011をNAT内側”192.168.1.11 (Bdog2)”のTCPポート60011にPort Forward、NAT外側のTCPポート60022をNAT内側”192.168.1.22 (Bdog3)”のTCPポート60022にPort Forwardするものとする。（それ以外の通信は不可とする。）

### 設定
Port Forwardの設定
```
$ sudo iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 60011 -j DNAT --to-destination 192.168.1.11:60011
$ sudo iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 60022 -j DNAT --to-destination 192.168.1.22:60022
```
同じく、FORWARDによるフィルタリングが必要。
```
$ sudo iptables -P FORWARD DROP
$ sudo iptables -A FORWARD -i enp0s3 -p tcp --dport 60011 -j ACCEPT
$ sudo iptables -A FORWARD -i enp0s3 -p tcp --dport 60022 -j ACCEPT
$ sudo iptables -A FORWARD -s 192.168.1.11 -p tcp --sport 60011 -j ACCEPT
$ sudo iptables -A FORWARD -s 192.168.1.22 -p tcp --sport 60022 -j ACCEPT
```
最終的な設定状況は下記。
```
$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DNAT       tcp  --  anywhere             anywhere             tcp dpt:60011 to:192.168.1.11:60011
DNAT       tcp  --  anywhere             anywhere             tcp dpt:60022 to:192.168.1.22:60022

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         

$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:60011
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:60022
ACCEPT     tcp  --  192.168.1.11         anywhere             tcp spt:60011
ACCEPT     tcp  --  192.168.1.22         anywhere             tcp spt:60022

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
```

### 検証
NAT内側”192.168.1.11 (Bdog2)”にて下記（netcat）を実行。TCPポート60011のListenである。
```
$ nc -l -p 60011
```
NAT内側”192.168.1.22 (Bdog3)”にて下記（netcat）を実行。TCPポート60022のListenである。
```
$ nc -l -p 60022
```
”172.16.1.11 (Bdog1)”にて、LubutuのNAT外側IPアドレスに向けて”netcat”を実行（TCPポート（60011および60022）を指定したTCPセッション確立）。
```
$ nc -z 172.16.1.254 60011
$ nc -z 172.16.1.254 60022
```
Wiresharkで取得したNAT外側の状況は下記となる。
![2_outside.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/4792eb91-6228-fe0b-08db-869d3096fd11.png)
特異事項なし。NAT内側の状況は下記となる。
![2_inside.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/fcfac0b8-f7e6-32f5-5294-7cc8a25482e3.png)
TCPポート60011通信は”192.168.1.11 (Bdog2)”へ、TCPポート60022通信は”192.168.1.22 (Bdog3)”へ転送されていることがわかる。

EOF