LinuxでIPマスカレードおよびパケットフィルタリングを実現するソフトウェアとしてipchains、iptablesがありますが、
カーネルバージョン2.4からiptablesがデフォルトで使用されるため今後使用されていくでしょう。
初期設定...
ipchainsとiptablesを同時に起動することはできません。まずipchainsがロードされているか確認します。
#lsmod
を実行し、ipchainsがロードされているのであれば削除します。
#rmmod ipchains
iptablesを使用するのであれば、ipchainsは必要ないので削除します。
#rpm -qa | grep ipchains
#rpm -e ipchains
次にiptable_natをロードします。
#modprobe iptable_nat
次の3つのモジュールがロードされていればOKです。最後にiptablesをLinux起動時に起動するようにします。
#chkconfig --level 2345 iptables on
iptablesの説明...
iptablesには初めから3つのfilter、nat、mangleテーブルが用意されています。このテーブルにより使用されるチェインが
異なります。このチェインにルールを記述することでパケットの検査が行われます。
テーブル名、チェイン名、チェインに記述されたルールとパケットを照合する位置を示します。
テーブル名、チェイン名
| テーブル名 |
チェイン名 |
| filter |
INPUT |
| OUTPUT |
| FORWARD |
| nat |
OUTPUT |
| PREROUTING |
| POSTROUTING |
| mangle |
OUTPUT |
| PREROUTING |
チェインの説明
| チェイン名 |
説明 |
| INPUT |
受信したパケットに対するチェイン |
| OUTPUT |
送信したパケットに対するチェイン |
| FORWARD |
対象サーバを経由するパケットに対するチェイン |
| PREROUTING |
受信時にパケットのアドレス変換をするチェイン |
| POSTROUTING |
送信時にパケットのアドレス変換をするチェイン |
チェインの位置
| 受信パケット→→→ |
|
→→→ |
|
→→→ |
|
→→→送信パケット |
|
↓ ↓ ↓
|
|
転送 |
|
↑ ↑ ↑
|
|
|
|
|
|
|
|
|
|
↓ ↓ ↓ 受信 |
|
|
|
↑ ↑ ↑ 送信 |
|
|
|
|
iptablesコマンド...
ルールを設定するにはiptablesコマンドを使用します。
iptables [ -t テーブル名 ] コマンド [ パラメータ ]
"-t テーブル名"には、filter、nat、mangleが指定可能です。指定しない場合はfilterが指定されます。
コマンドにはiptablesコマンドが実行する動作を指定します。
コマンドオプション
| -A | 指定したチェインにルールを追加する。 |
| -F | 指定したチェインの内容を全て消去する。 |
| -h | ヘルプを表示する。 |
| -L | 指定したチェインのルールを一覧表示する。(チェイン名を指定しない場合はすべてのチェインのルールを表示する。) |
| -N | 指定した名前でユーザ定義チェインを作成する。 |
| -P | デフォルト(ルールが最後までマッチしなかった場合)に適用されるターゲットを指定する。 |
| -X | 指定したユーザ定義チェインを削除する。 |
| -Z | 全てのチェインのパケットカウンタとバイトカウンタをクリアする。 |
パラメータは以下のとおりです。
パラメータ
| -d IPアドレス | あて先を指定する。 |
| -i インタフェイス名 | パケットを受信するインタフェイスを指定する。 |
| -j ターゲット | ターゲットを指定する。ターゲットにはACCEPT、DROP、RETURN、LOG、REJECT、ユーザ定義チェインを指定できます。 |
| -o インタフェイス名 | パケットを送信するインタフェイスを指定する。 |
| -p プロトコル名 | プロトコルを指定する。tcp,、udp、 icmp、 allが指定できる。 |
| -s IPアドレス | 送信元を指定する。 |
ターゲットは以下のとおりです。
ターゲット
| ACCEPT | マッチしたパケットを通す。(接続を許可する。) |
| DROP | マッチしたパケットを破棄する。(接続を拒否する。) |
| LOG | マッチしたパケットをログに記憶する。 |
| REJECT | マッチしたパケットの送信元にICMPのエラーメッセージを返信し、DROPする。 |
| RETURN | ユーザ定義チェイン内であれば呼び出し元に返り、組み込み済みチェインであればチェインポリシーが適用される。 |
| ユーザ定義チェイン | ターゲットに指定されたユーザ定義チェインに移動する。 |
"-j LOG"をターゲットに指定した場合のオプション
--log-level レベル数値 | レベル名
ログを記録するレベルを指定する。デフォルトはwarningで、
debug(7)、info(6)、notice(5)、warning(4)、err(3)、crit(2)、alert(1)、emerg(0)が指定できる。
--log-prefix 文字列
記録するログの先頭に文字列を追加する。(29文字まで)
-p を指定した後か明示的に
-m を指定することで拡張モジュールを指定できる。
"-p tcp"を指定した場合の拡張オプション
--dport [!] ポート番号 | ポート名
あて先ポートを指定する。ポート番号またはポート名を指定することができる。
ポート番号:ポート番号と指定することでポート番号を範囲指定することも可能。
--sport [!] ポート番号 | ポート名
送信元ポートを指定する。ポート番号またはポート名を指定することができる。
ポート番号:ポート番号と指定することでポート番号を範囲指定することも可能。
[!]--syn
SYN、ACK、FINフラグをチェックしてSYNフラグだけONであるパケットがマッチする。
--tcp-flags [!] checkflags flags
チェックするフラグを指定する。SYN、ACK、FIN、RST、URG、PSH、ALL、NONEが指定できる。
"checkflags"にはチェックするフラグを指定する。"flags"にはONになっているフラグを指定する。
"-p udp"を指定した場合の拡張オプション
--dport [!] ポート番号 | ポート名
あて先ポートを指定する。ポート番号またはポート名を指定することができる。
ポート番号:ポート番号と指定することでポート番号を範囲指定することも可能。
--sport [!] ポート番号 | ポート名
送信元ポートを指定する。ポート番号またはポート名を指定することができる。
ポート番号:ポート番号と指定することでポート番号を範囲指定することも可能。
"-p icmp"を指定した場合の拡張オプション
--icmp-type [!]タイプ番号 | タイプ名
ICMPのタイプ番号またはタイプ名が指定できる。
タイプ名にはEcho Reply(0)、Destination Unreachable(3)、Source Quench(4)、Redirect(5)、Echo Request(8)、Time Exceeded(11)、
Parameter Problem(12)、Timestamp Request(13)、Timestamp Reply(14)、Information Request(15)、Information Reply(16)、
Address Mask Request(17)、Address Mask Reply(18)がある。
よく使用されるPingを許可したいのであれば、Pingリクエスト(Echo Request(8))およびそのPing応答(Echo Reply(0))
を許可すればよい。
"-m limit"を指定した場合の拡張オプション
--limit 回数/T
単位時間あたりにマッチする最大値をする。"T"にはsecond、minute、hour、dayが指定できる。
ログの肥大化を防ぐことができる。
"-m state"を指定した場合の拡張オプション
--state 接続状態
接続状態を知ることができる。接続状態にはNEW、INVALID、ESTABLISHED、RELATEDが指定できる。
NEWは新規接続のパケット、INVALIDは既存パケットと関係のないパケット、ESTABLISHEDは既存パケットと関係あるパケット
RELATEDは新規接続のパケットであるが、既存パケットに関係のあるパケットである。
これにより、いちいち応答パケットを許可する設定をしなくても済みます。
IPマスカレードする(MASQUERADE)
IPマスカレードするにはまずnatテーブルのPOSTROUTINGチェインを指定します。そしてターゲットにMASQUERADEを指定します。
MASQUERADEはnatテーブルのPOSTROUTINGチェインのみで使用可能です。
#iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
これでプライベートアドレスの割り当てられたローカルネットワークのホストもデフォルトゲートウェイにこのサーバのアドレス
を指定することでインターネットに接続できます。
※ "!"は以外という意味です。例えば ! 192.168.0.1は192.168.0.1以外が対象ということです。
iptablesを設定する前に...
iptablesを設定する前に環境に応じて変更する箇所があります。これらは必須ではありません。
環境により設定しなくてもよいものもありますので、自分の環境に合わせて判断してください。
IPマスカレードを使用したいのであれば
#echo 1 > /proc/sys/net/ipv4/ip_forward
を実行します。
DHCPによりIPアドレスを動的に割り当てている場合は
#echo 1 > /proc/sys/net/ipv4/ip_dynaddr
を実行します。
Broadcast pingに応答したくないのであれば
#echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
を実行します。
SYN Flood攻撃を防ぐのであれば
#echo 1 > /proc/sys/net/ipv4/tcp_syncookies
を実行します。
Source-routedパケットを拒否するのであれば
を実行します。
ICMP Redirectパケットを拒否するのであれば
IPマスカレードしながらFTPを利用するには、次の2つのモジュールをカーネルに組み込みます。
iptablesの設定例...
filterテーブル、natテーブルのチェイン、ユーザ定義チェインを全てクリアする。
デフォルトのターゲットを拒否に設定する。
プライベートアドレスからのインタフェイスppp0へのアクセスを拒否する。
ppp0から送信されるDNS問い合わせを許可する。
#iptables -A OUTPUT -o ppp0 -p udp --dport 53 -j ACCEPT
ppp0へ送信された80番ポート(http)へのアクセスを許可する。
#iptables -A INPUT -i ppp0 -p tcp --dport 80 -j ACCEPT
DHCPを許可する。
#iptables -A INPUT -i ppp0 -s 0.0.0.0/0 -d 0.0.0.0/0 -p udp --sport bootps --dport bootpc -j ACCEPT
応答パケットを許可する。
このような感じで設定していきます。あとは応用してください。
ユーザ定義チェインの作成...
組み込み済みチェイン以外にユーザが自由にチェインを作成することができます。ターゲットにユーザ定義チェイン
を指定した場合、パケットはユーザ定義チェインのルールと照合を開始し、ルールとマッチした場合はそこでパケットの照合を終えますが、
ユーザ定義チェイン内でルールとマッチしなかった場合は元のチェインに返り、そこからまたルールとパケットの照合を開始します。
ログを採取した後パケットを破棄するルールを記述したユーザ定義チェインlog_dropの作成例
後はこのlog_dropチェインをターゲットに指定します。
ppp0からの80番ポート(http)へのアクセスをログに取り拒否する。
#iptables -A OUTPUT -o ppp0 -p tcp --dport 80 -j log_drop
これで、このルールにマッチしたパケットはlog_dropチェインに移動し、log_dropチェインのルールと照合を始めます。
ユーザ定義チェインから他のユーザ定義チェインに移動することもできますが、ループ構造になっていてはいけません。
例えばユーザ定義チェインa内のルールのターゲットにユーザ定義チェインbが指定されている場合、ユーザ定義チェインb内のルールのターゲット
にユーザ定義チェインaは指定してはいけません。この条件にあてはまるパケットは破棄されるようです。
またインタフェイスやパケットの方向別にユーザ定義チェインを作成することでルールの設定がわかりやすくなります。
インターネット側のインタフェイスppp0を外部、ローカル側のインタフェイスeth1を内部、設定されるホストをサーバとすると、
ppp0から送信されるパケットのチェインserver_wan(サーバ--->外部)
ppp0へ送信されるパケットのチェインwan_server(外部--->サーバ)
eth1から送信するパケットのチェインserver_lan(サーバ--->内部)
eth1へ送信されるパケットのチェインlan_server(内部--->サーバ)
ppp0からeth1へ転送するパケットのチェインwan_lan(外部--->内部)
eth1からppp0へ転送するパケットのチェインlan_wan(内部--->外部)の作成例
後はそれぞれ、設定したいルールを該当するチェインに追加します。
例えば外部からサーバの80番ポートへのアクセスを許可したいのであれば
#iptables -A wan_server -p tcp --dport 80 -j ACCEPT
とします。これで直感的に外部からサーバに入ってくるパケットのルールだとわかるので理解しやすいです。
スクリプトファイルにする...
これまで設定してきたiptablesのフィルタリングルールはRAMに格納されるので、再起動等で消えてしまいます。
よってこのiptablesのフィルタリングルールをスクリプトファイルに記述し、システム起動時やインターネット接続時に自動で実行するようにすれば再設定する手間が省けます。
また変数を作成することでフィルタリングルールの修正も楽になりますし、わかりやすくなります。以上のことをふまえてスクリプトファイルにします。ファイル名はここではfiltertbとします。
(あくまで例のために作成したものです。この設定のまま使用するのはやめましょう。)
#!/bin/sh
##################################################
# Initialize
##################################################
#LoadModule
modprobe iptable_nat
modprobe ip_nat_ftp
modprobe ip_conntrack_ftp
#Enable IP Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
#Enable Dynamic IP
echo 1 > /proc/sys/net/ipv4/ip_dynaddr
#Measure of SYN flood
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
#Measure of Broadcast ping
echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
#Refusal of Source-routed packets
for i in /proc/sys/net/ipv4/conf/*/accept_source_route;do
echo 0 > $i
done
#Refusal of ICMP redirect
for i in /proc/sys/net/ipv4/conf/*/accept_redirects;do
echo 0 > $i
done
#Setup of a variable
WAN_IF=eth0
LAN_IF=eth1
LOOPBACK_ADDR=127.0.0.0/8
PRV_CLASS_A_ADDR=10.0.0.0/8
PRV_CLASS_B_ADDR=172.16.0.0/12
PRV_CLASS_C_ADDR=192.168.0.0/16
CLASS_E_ADDR=240.0.0.0/5
ANY_ADDR=0.0.0.0/0
WAN_ADDR=`ifconfig eth0 | sed -e 's/^.*inet addr:\([0-9.]*\).*/\1/p' -e d`
#Flush All Chain
iptables -F
iptables -t nat -F
iptables -X
iptables -Z
#Default Filtering Chain
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
##################################################
# Make New Chain
##################################################
#wan_server : WAN--->Server
#lan_server : LAN--->Server
#server_wan : Server--->WAN
#server_lan : Server--->LAN
#wan_lan : WAN--->LAN
#lan_wan : LAN--->WAN
#New Filtering_Chain
iptables -N wan_server
iptables -N lan_server
iptables -N server_wan
iptables -N server_lan
iptables -N wan_lan
iptables -N lan_wan
iptables -A INPUT -i $WAN_IF -j wan_server
iptables -A INPUT -i $LAN_IF -j lan_server
iptables -A OUTPUT -o $WAN_IF -j server_wan
iptables -A OUTPUT -o $LAN_IF -j server_lan
iptables -A FORWARD -i $WAN_IF -o $LAN_IF -j wan_lan
iptables -A FORWARD -i $LAN_IF -o $WAN_IF -j lan_wan
#New Loging_Drop_Chain
iptables -N log_drop
iptables -A log_drop -m limit --limit 1/s -j LOG
iptables -A log_drop -j DROP
##################################################
# Private,ClassE,Loopback,Bcast,Spoofing
##################################################
#Server-->WAN
for i in $PRV_CLASS_A_ADDR $PRV_CLASS_B_ADDR $PRV_CLASS_C_ADDR $CLASS_E_ADDR $LOOPBACK_ADDR
do
iptables -A server_wan -d $i -j log_drop
done
#WAN--->Server
for i in $PRV_CLASS_A_ADDR $PRV_CLASS_B_ADDR $PRV_CLASS_C_ADDR $CLASS_E_ADDR $LOOPBACK_ADDR
do
iptables -A wan_server -s $i -j log_drop
done
#LAN-->WAN
for i in $PRV_CLASS_A_ADDR $PRV_CLASS_B_ADDR $PRV_CLASS_C_ADDR $CLASS_E_ADDR $LOOPBACK_ADDR
do
iptables -A lan_wan -d $i -j log_drop
done
#WAN-->LAN
for i in $PRV_CLASS_A_ADDR $PRV_CLASS_B_ADDR $PRV_CLASS_C_ADDR $CLASS_E_ADDR $LOOPBACK_ADDR
do
iptables -A wan_lan -s $i -j log_drop
done
#Broadcast
iptables -A wan_server -d 255.255.255.255/32 -j log_drop
#Spoofing WAN_ADDR
iptables -A wan_server -s $WAN_ADDR -j log_drop
#Ident
iptables -A wan_server -p tcp --dport ident -j REJECT --reject-with tcp-reset
##################################################
# LAN--->WAN IP Masquerade
##################################################
#IPMasquerade
iptables -t nat -A POSTROUTING -o $WAN_IF -j MASQUERADE
##################################################
# lo Policy
##################################################
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
##################################################
# Server--->LAN Policy
##################################################
iptables -A server_lan -j ACCEPT
##################################################
# LAN--->Server Policy
##################################################
iptables -A lan_server -j ACCEPT
##################################################
# Server--->WAN Policy
##################################################
#The packet to which connection establishes or relates
iptables -A server_wan -m state --state ESTABLISHED,RELATED -j ACCEPT
#ICMP(Ping)
iptables -A server_wan -p icmp --icmp-type 8 -j ACCEPT
#SMTP(25/TCP)
iptables -A server_wan -p tcp --dport 25 -j ACCEPT
#DNS(53/UDP)
iptables -A server_wan -p udp --dport 53 -j ACCEPT
#NTP(123/UDP)
iptables -A server_wan -p udp --dport 123 -j ACCEPT
#Except the above
iptables -A server_wan -j log_drop
##################################################
# WAN--->Server Policy
##################################################
#The packet to which connection establishes or relates
iptables -A wan_server -m state --state ESTABLISHED,RELATED -j ACCEPT
#ICMP(Ping)
iptables -A wan_server -p icmp --icmp-type 0 -j ACCEPT
#FTP-data(20/TCP)
iptables -A wan_server -p tcp --dport 20 -j ACCEPT
#FTP(21/TCP)
iptables -A wan_server -p tcp --dport 21 -j ACCEPT
#SMTP(25/TCP)
iptables -A wan_server -p tcp --dport 25 -j ACCEPT
#HTTP(80/TCP)
iptables -A wan_server -p tcp --dport 80 -j ACCEPT
#POP3(110/TCP)
iptables -A wan_server -p tcp --dport 110 -j ACCEPT
#Except the above
iptables -A wan_server -j log_drop
##################################################
# LAN--->WAN Policy.....ACCEPT
##################################################
#The packet to which connection establishes or relates
iptables -A lan_wan -m state --state ESTABLISHED,RELATED -j ACCEPT
#ICMP(Ping)
iptables -A lan_wan -p icmp --icmp-type 8 -j ACCEPT
#FTP-data(20/TCP)
iptables -A lan_wan -p tcp --dport 20 -j ACCEPT
#FTP(21/TCP)
iptables -A lan_wan -p tcp --dport 21 -j ACCEPT
#SMTP(25/TCP)
iptables -A lan_wan -p tcp --dport 25 -j ACCEPT
#HTTP(80/TCP)
iptables -A lan_wan -p tcp --dport 80 -j ACCEPT
iptables -A lan_wan -p tcp --dport 8080 -j ACCEPT
#POP3(110/TCP)
iptables -A lan_wan -p tcp --dport 110 -j ACCEPT
#NTP(123/UDP)
iptables -A lan_wan -p udp --dport 123 -j ACCEPT
#HTTPS(443/TCP)
iptables -A lan_wan -p tcp --dport 443 -j ACCEPT
#Except the above
iptables -A lan_wan -j log_drop
##################################################
# WAN--->LAN Policy.....ACCEPT
##################################################
#The packet to which connection establishes or relates
iptables -A wan_lan -m state --state ESTABLISHED,RELATED -j ACCEPT
#ICMP(Ping)
iptables -A wan_lan -p icmp --icmp-type 0 -j ACCEPT
#Except the above
iptables -A wan_lan -j log_drop
あとは応用してください。一度フィルタリングルールを設定しただけで終わりでありません。何度も定期的にフィルタリングルールを見直す必要があります。
正しくフィルタリングルールが適用されているかチェックします。
sh filtertab実行時にエラーが出力される場合はfiltertabスクリプトファイルの構文などを見直しましょう。
システム起動時にiptablesのフィルタリングルールを適用したい場合は、作成したスクリプトファイルを/etc/rc.d/init.d/filtertabファイルとして保存し、自動起動させたいランレベルのディレクトリにリンクさせます。(デフォルトランレベルが3の場合)
以上で起動時にiptablesのフィルタリングルールが適用されます。
RP-PPPoEによりインターネットに接続している場合は、adsl-startコマンド実行時に実行される/etc/ppp/firewall-masqファイル
にiptablesのスクリプトを記述してもよいでしょう。この場合、起動時にはフィルタリングは適用されず、adsl-startコマンド
を実行したインターネット接続時に適用されます。