試して学ぶiptables、ウェブ閲覧できるまで

iptablesを理解するために、
ノートPC(Linux)で実際にポートを開放してウェブを閲覧できるまでを試します。

## 初期状態

~~~
# iptables -L        
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

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

全開なのでホワイトリスト方式にし、ポート開放を行いウェブ閲覧を目指します。

## デフォルトポリシーの設定

ホワイトリスト方式にする

~~~
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
~~~

-t オプションを指定しない場合、デフォルトのテーブルはfilterテーブルです。

qiitaに繋がらなくなりました。
OUTPUTは全開ですが、INPUTがまったくとれない状態です。
つまり、pingの応答もとれません。

~~~
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
~~~

## pingを使えるようにする

pingはicmpプロトコルを使っているので許可します。

~~~
# iptables -A INPUT -p icmp -j ACCEPT
# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=52 time=12.4 ms
~~~

名前解決はできるでしょうか？

~~~
# ping google.com
ping: google.com: 名前またはサービスが不明です
~~~

## 名前解決をできるようにする

DNSプロトコルは53番ポートでudpとtcpを使うらしいので両方を開けます。
※通常はudpを使い、パケットサイズがMTUの1500超えるとtcp使うとか

~~~
# iptables -A INPUT -p udp --sport 53 -j ACCEPT
# iptables -A INPUT -p tcp --sport 53 -j ACCEPT
# dig google.com

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> google.com
;; global options: +cmd
;; connection timed out; no servers could be reached
~~~

解決できないです。。おかしい。
※これはsystemd-resolvedが動作している環境の話です。そうでない場合は上記で動作しているはずです。読み飛ばしてください。

~~~
# cat /etc/resolv.conf
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients to the
# internal DNS stub resolver of systemd-resolved. This file lists all
# configured search domains.
#
# Run "systemd-resolve --status" to see details about the uplink DNS servers
# currently in use.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.

nameserver 127.0.0.53
options edns0
# ss -ln | grep "127.0.0.53"
udp  UNCONN 0      0                                              127.0.0.53%lo:53                                                 0.0.0.0:*                    
tcp  LISTEN 0      128                                            127.0.0.53%lo:53                                                 0.0.0.0:* 
~~~

systemd-resolvedがローカルの53番ポートで一次請けするみたいなので、destinationも開ける必要がありそうです。
**再度注意：これはsystemd-resolvedが動作していないマシンでは不要**

~~~
# iptables -A INPUT -p udp --dport 53 -j ACCEPT
# iptables -A INPUT -p tcp --dport 53 -j ACCEPT
# dig google.com

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62225
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;google.com.			IN	A

;; ANSWER SECTION:
google.com.		163	IN	A	172.217.24.142

;; Query time: 13 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Fri Dec 27 17:47:57 JST 2019
;; MSG SIZE  rcvd: 55
~~~

解決できました。（実は結構ハマりました:sweat_smile:

でもまだqiitaにはつながりません。
http(s)の応答を受信できるようにする必要があります。

## http(s)の応答を許可

~~~
# iptables -A INPUT -p tcp --sport 80 -j ACCEPT
# iptables -A INPUT -p tcp --sport 443 -j ACCEPT
~~~

qiitaに接続できました。

# 設定の確認と保存

ここまでの設定は以下のコマンドで確認でき、リダイレクトで保存できます。

~~~
iptables-save
# Generated by iptables-save v1.6.1 on Sat Dec 28 13:08:20 2019
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
# Completed on Sat Dec 28 13:08:20 2019
# Generated by iptables-save v1.6.1 on Sat Dec 28 13:08:20 2019
*filter
:INPUT DROP [542:171507]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [2523:785906]
-A INPUT -p icmp -j ACCEPT
-A INPUT -p udp -m udp --sport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --sport 53 -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -p tcp -m tcp --sport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --sport 443 -j ACCEPT
COMMIT
# Completed on Sat Dec 28 13:08:20 2019
~~~

# 設定の復元

保存した設定ファイルから設定を復元するには以下のコマンドで可能です。

~~~
# iptables-restore [設定ファイル名]
~~~

# 片付け

元の状態に戻すには 

- -Fオプションでruleの設定を削除  
  （テーブル毎に削除されます。今回はfilterテーブルまでのため-tオプションは不要ですが、natテーブルを修正した場合には-tで指定して削除してください。）
- -Pでポリシーを元に戻す

~~~
# iptables -F
# iptables -P INPUT ACCEPT
# iptables -P FORWARD ACCEPT
~~~

# まとめ

デフォルトポリシーで内部に入ってくるパケットを全て弾くところから、
ウェブ閲覧までに必要なポート開放を行ってみました。
iptablesはセキュリティに関わる設定なので、正しい知識を身につけるようにしたいです。