LoginSignup
3
5

More than 5 years have passed since last update.

iptables でローカルの上位ポートに転送しているときにそのポートへの直接アクセスを禁止する

Posted at

下記の様な方法でウェルノウンポートへのアクセスを別の上位ポートへ転送したときに、上位ポートへの直接のアクセスを禁止する方法。

準備

3000 ポートでサーバを立てます。

$ nc -k -l 3000

iptables で 80 ポートに届いたパケットを 3000 ポートへ REDIRECT します。

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000

別ホストから 80 ポートと 3000 ポートに接続すると、どちらでも接続できます。

$ date | nc -n -v 192.0.2.123 80
Connection to 192.0.2.123 80 port [tcp/*] succeeded!

$ date | nc -n -v 192.0.2.123 3000
Connection to 192.0.2.123 3000 port [tcp/*] succeeded!

失敗その1

サーバのバインドアドレスを 127.0.0.1 にしてみました。

$ nc -k -l 127.0.0.1 3000

80 ポートと 3000 ポートの両方で繋がらなくなりました。

$ date | nc -n -v 192.0.2.123 80
nc: connect to 192.0.2.123 port 80 (tcp) failed: Connection refused

$ date | nc -n -v 192.0.2.123 3000
nc: connect to 192.0.2.123 port 3000 (tcp) failed: Connection refused

REDIRECT したからといって eth0 に来たパケットを lo に転送しているわけではないのでダメなのだと思います。

失敗その2

INPUT チェインで 3000 ポートをフィルタしてみました。

$ sudo iptables -F
$ sudo iptables -F -t nat

$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
$ sudo iptables -A INPUT -p tcp --dport 3000 -j LOG
$ sudo iptables -A INPUT -p tcp --dport 3000 -j REJECT --reject-with tcp-reset

両方のポートで繋がらなくなりました。

$ date | nc -n -v 192.0.2.123 80
nc: connect to 192.0.2.123 port 80 (tcp) failed: Connection refused

$ date | nc -n -v 192.0.2.123 3000
nc: connect to 192.0.2.123 port 3000 (tcp) failed: Connection refused

filter テーブルの INPUT よりも nat テーブルの PREROUTING の方が先なので当たり前でした。

成功その1

nat テーブルの PREROUTING よりも前にフィルタすればいいのですが filter テーブルで PREROUTING よりも先に適用されるチェインはありません。

なので mangle テーブルの PREROUTING でマークして、マークされたパケットを filter テーブルの INPUT で REJECT します。

sudo iptables -F
sudo iptables -F -t nat
sudo iptables -F -t mangle

sudo iptables -t mangle -A PREROUTING -p tcp --dport 3000 -j MARK --set-mark 0x01
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
sudo iptables -A INPUT -p tcp --dport 3000 -m mark --mark 0x01 -j REJECT --reject-with tcp-reset

80 ポートでだけ繋がるようになりました。

$ date | nc -n -v 192.0.2.123 80
Connection to 192.0.2.123 80 port [tcp/*] succeeded!

$ date | nc -n -v 192.0.2.123 3000
nc: connect to 192.0.2.123 port 3000 (tcp) failed: Connection refused

成功その2

REJECT ではなく DROP なら mangle テーブルの PREROUTING チェインでできました。

sudo iptables -F
sudo iptables -F -t nat
sudo iptables -F -t mangle

sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
sudo iptables -t mangle -A PREROUTING -p tcp --dport 3000 -j DROP

パケットがドロップされるのでタイムアウトまで待たされますけどね。

$ date | nc -n -v -w 3 192.0.2.123 80
Connection to 192.0.2.123 80 port [tcp/*] succeeded!

$ date | nc -n -v -w 3 192.0.2.123 3000
nc: connect to 192.0.2.123 port 3000 (tcp) timed out: Operation now in progress

成功その3

nat テーブルの PREROUTING でリッスンしていない適当なポートに REDIRECT すれば、REJECT と同じような動作になります。

sudo iptables -F
sudo iptables -F -t nat
sudo iptables -F -t mangle

sudo iptables -t nat -A PREROUTING -p tcp --dport 3000 -j REDIRECT --to-ports 1
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000

1 ポートでリッスンしていないことが前提になりますけど。

$ date | nc -n -v 192.0.2.123 80
Connection to 192.0.2.123 80 port [tcp/*] succeeded!

$ date | nc -n -v 192.0.2.123 3000
nc: connect to 192.0.2.123 port 3000 (tcp) failed: Connection refused

さいごに

「成功その1」が一番妥当っぽい気がします。

「成功その2」は mangle テーブルで DROP とかしてもいいんですかね?

「成功その3」はちょっとワイルドすぎると思います。

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5