|
追加追加で少しまとまりがなくなってところ、hoehoeさん再度まとめて編集していただきました。感謝。
ドキュメント全体の流れは下記のようになっています。(クリックすれば飛べます。)
1.ファイアウォールとは
2.ipfwでフィルタリング-[ 基本 ]
3.ipfwでフィルタリング-[ 応用 ]
4.番外編-TcpWrapperとの違い
- Mac OS Xで作るファイアウォール[ファイアウォールとは] -
[ Index ]
----------------------------------------------------------------
1.ファイアウォールとは
2.ipfwでフィルタリング-[ 基本 ]
3.ipfwでフィルタリング-[ 応用 ]
4.番外編-TcpWrapperとの違い
----------------------------------------------------------------
はじめに:
MacOSXにはBSDと同じipfwというパケットフィルタリング型のファイアウォールが実装されています(余談ですが、Linuxのipchains---その前はipwadm---はBSDのipfwの書き直し---パクリ---ではないかとLinuxのHOWTOで言われています)。これによってファイアウォールを構築し、セキュリティを高めることが出来るようになります。
また、かならず各自の責任において行ってください(下手をするとパケットがローカルホストにも流れなくなります。リモート操作で行うとローカルログインも不可能になりますので)。
ファイアウォールとは:
究極的な対策は、コンピュータをネットワークに繋げないことです。そうすれば、クラッキングやウィルスによる、ネットワークを介した不正なアクセスは一切ありません。しかし現実にはこの対策は非常に困難です。そこで登場するのが、Fire-wallやIDS(侵入検知システム)です。
Fire-wallには主に2つの異なるタイプがあるそうです。一つは、(厳密には)パケットフィルタリングルータと呼ばれるタイプのもの。もう一つはProxy(代理)サーバーと呼ばれるタイプのものです。詳しくはFreeBSDのオンラインマニュアル[
ipfw(8) ]やドキュメントを参照してください、そちらに詳しく解説がしてあります。ここで扱うipfwはルータタイプのファイアウォールです。
パケットフィルタリングルータ:
ルータとは、二つまたはそれ以上のネットワークの間でパケット(小包)の転送をおこなうマシンのことです。フィルタリングとはパケットをルールリストと比較して、転送するかしないかを決めることです。パケット(小包)の通過を許すべきかどうかを決めるルールを自分で定義することによって、初めてフィルタリングが有効になります。
ipfwで何ができるか:
ipfwは、カーネル内部にあってパケットのフィルタリングとアカウンティングをおこなうシステムです。ルーティングの決定をおこなう際に、これらは互いに協力して、カーネルで使用されるルールを定義したり、現在使用されているルールを問い合わせたりすることができます
ipfwは互いに関連する二つの部分からなっています。ファイアウォールセクションはパケットフィルタリングをおこないます。また、IPアカウンティングセクションはファイアウォールセクションのものと似たルールに基づいてルータの使用を追跡します。これにより、(たとえば)特定のマシンからルータへのトラフィックがどのくらい発生しているか調べたり、どれだけのWWW(WorldWideWeb)トラフィックがフォワードされているかを知ることができます。
さらに、ipfwはカーネルに組み込まれているためOSのプロセスのみで動作します。従ってNATを併用したときにkernel + 1(NAT)のプロセスとなり、とてもお得(?)です。
[ どんなファイアウォールにするか ]
ファイアウォールに限らず、どんな時でも自分がこれから何のために何をするのか、最終的な目標は何かをきちんと把握するのはとても重要です。それによって得られる結果や、手段、使う道具が異なってくるからです。Web
serverを立てるならどんなファイアウォールにするのか、Mail serverであればWeb server等とどのように違いが出てくるのかを把握しなくてはなりません(もちろん、それぞれに特化したファイアウォールを構築するのが理想的ですが)。さらに、本当にルータタイプのファイアウォールでよいかも考えてみてください。場合によってはProxy型の方が効率的かもしれません。
話をipfwに戻しましょう。ルータタイプのファイアウォールも例外ではありません。自分が公開したいと考えているサービスが何かはあなた自身が知っています。まずはそれにあわせて一つずつルールを作っていけばよいでしょう。
[ ルールの設計 ]
実際にルールを作るときは、絵(図)を書いてパケットがどう流れるかを見るとよいでしょう。そうすることで、ルールの設計が容易になります。
今回は以下のようなフィルタリングルールを作成しました。
1.Webサーバに対しては、どこからでも80/TCPによるアクセスを許可
2.DNSサーバは外部にあるものとし、信頼する
3.icmpによるping,tracerouteは許可
4.ローカルエリア内のホストは信頼する(信頼できなければProxyなどで制御する)
5.NATによる変換を行う
6.上記以外はすべて不許可
それでは実際にこのルールに従って、ipfwを設定していきましょう。
- Mac OS Xで作るファイアウォール[ipfwでフィルタリング 基本編] -
前回は、ファイアウォールとは何か、どんなファイアウォールにするのか、そしてファイアウォールを設定するためのルールを決めました。今回は実際にipfwコマンドを使ってみましょう。
[ ipfw コマンド ]
では、実際に1つルールを作ってみましょう。Terminalからコマンドを打ちます。
#rootになります
% su
Password: ******
root#
icmpのパケットをいかなる場所からも到達不可能にします
root# ipfw add deny icmp from any to any
※注意 >> [ ipfw add deny all from any to any ] とするとリモートからは「何も」できなくなります。sshで別マシンから作業している場合などは要注意です。また、ipfwは書かれた順によって優先度が決まります(ルール番号が若い方が優先度が高い)。
ルールを表示してみます
root# ipfw -a l または ipfw show
-> 00100 deny icmp from any to any
### このルールが一番優先になります ###
とあればOKです。
ためしにPingを飛ばしてみましょ
root# ping localhost
んで、ret=-1、packet loss が 100%ならOKです。こういった感じの書式になります(まだまだオプションがありますが今回は基本をしっかり抑えておきましょう)。
[ ipfw書式 ]
---------------------------------------------------------------
ipfw
[ -q/-f ]
add/delete
allow/deny
[ log ]
tcp/ip/icmp
from domain/ip-address:mask-bit/hosts port-number
to domain/ip-address:mask-bit/hosts port-number
via interface
---------------------------------------------------------------
1行で記述のこと
※allow はpass,acceptと、denyはdropと、ipはall、と置き換えることができます
※ポートを指定する場合はプロトコルを明示的に指定(ip/all以外で)しなければいけません。
Ex)
ipfw -q add drop all from 192.168.0.0/24 to any 137-139
ではなくて
ipfw -q add drop tcp from 192.168.0.0/24 to any 137-139
とTCPを明示的に指定してやります。
こうすることでローカルからSambaにアクセスできなくなります
これでは困るので、いったんルールを開放します
root# ipfw flush
Are you sure? [yn] y
Flushed all rules.
root# ipfw show
65535 4116 628054 allow ip from any to any
あとはずっとこれの繰り返しになりますが、ShellScriptはインタープリタ(1行読み込み)型言語なので、ルールの位置を間違えるとエライことになりますのでご注意を
んでもって、コマンドをいちいち打つのはメンドイのでファイルにルールを書いて、まとめて実行かけちゃいましょう。テキトーなディレクトリにipfw.shファイルを作成(Desktopにでも)。中身はコチラ(プレーンテキストで作成のこと。リッチじゃだめよ)
[ipfw.sh]
---------------------------------------------------------------------------
#!/bin/sh
# 2002/04/02/ - hoehoe
# ipfw command
# 他のShellを使用している場合はtcshを指定してください
# Bash等ではcommand not foundになります
# コマンドやホストのipアドレスを変数に入れます
set fwq="/sbin/ipfw -q"
set fw="/sbin/ipfw"
set myhost="192.168.0.10"
set mynet="192.168.0.0/24"
# ルールを初期化
$fw -f flush
# ループバックは許可
$fwq add accept all from any to any via lo0
# ローカルエリアは許可
$fwq add accept all from $mynet to $myhost
$fwq add accept all from $myhost to $mynet
# その他の接続を拒否
$fwq add drop all from any to any
# ルールカウンタをゼロにする
$fw zero
[EOF]
---------------------------------------------------------------------------
ファイルができたら、次はディレクトリを作成しコピー
root# mkdir /usr/local/sbin/
root# chmod -R 755 /usr/local/sbin/
root# cp ./Desktop/ipfw.sh /usr/local/sbin/
ipfw.shを実行しましょう
root# source /usr/local/sbin/ipfw.sh
Flushed all rules.
Accounting cleared.
と表示されれば無事にルールが有効になりました。
こうやってファイルに書いてルール・チェーンを繋げていきます。このファイルを元にNATを設定してみましょう。
- Mac OS Xで作るファイアウォール[ipfwでフィルタリング 応用編] -
今回は応用編ですので少し難しくなるかもしれません。ゆっくりでいいので一つ一つ見ていってください。前回作成したipfw.shスクリプトファイルに変更を加えていきます。今回ipfwと併用して行うのは以下の4点です。
1.NAT(ネットワークアドレス変換)を行う
2.ステートフルなフィルタリングに対応する
3.ログを取れるようにする
4.以前作ったルールを適用する
ルールを変更する前に、簡単な説明と現在のホストの状況確認をしていきます。
※本来NATはネットワークカード(略してNIC)を2枚使用して行いますが、確認が取れないためここでは1枚のNICで行っています。
[ NAT ]
普通、インターネットなどの外部のネットワークに組織内のホストを繋げるには、ゲートウェイとなるホストにNICを複数枚挿し、グローバルIPとプライベートIPの変換を行います(インターフェースはネットワークカードでもAirMacでもOKですが、AirMacを使う場合はHDDがHFS+でフォーマットされていないといけません)。
[ ステートフルなフィルタリング ]
これについてはFTPを例にとって説明しますね。FTPはファイル転送用のプロトコルとして広く知られていると思います。このFTPの大きな特徴はポートをコマンド用とデータ用とで2つ使うところにあります。コマンド用(ftpdなどでServerにログインすると、lsやget、putなどを使うことができます)のポート番号は通常21番で固定です。しかしデータ用は昔は20番で固定だったのですが、最近は動的に空いているポートを探してそのポートでデータ転送をさせるようにしているようです(まぁ現実的な視点から考えると、当然と言えなくも無いですが)。
NATやIPマスカレードでIPアドレスをいじっているとGatwayでIPアドレスが書き換わるので(アドレス変換のタイミングにもよりますが)、書き換わったIPアドレスに対応させなくてはいけなくなります。そこに、ipfwで単純なフィルタリングをかましているとFTPのログインはできるけど、データが持って来れないということになってしまいます。さらに、家庭においては自宅でサーバーを立てようとしたときに、ネットワークゲーム(ディアボロとかね)をやろうとしたけど繋がらないということに出くわすかもしれません。それを解決するのがステートフルなフィルタリングというやつです。これを使うと動的にポートを開け閉めできるようになります。
ipfwでは「keep-state」と「check-state」の2つを使ってステートフルなフィルタリングを実現しています。これらを使うことにより、LAN
上のクライアントがインターネットのサーバにアクセスした時にその事実を記憶しておき、そのインターネットのサーバからLAN上のクライアントへのレスポンスを一定時間許可することができます。例えばLAN上のUDPクライアント(ICQ
等)にインターネットへのアクセスを許しながら、インターネットからLAN上のUDPサーバへのパケットの送信を禁止することができます。 現在のバージョンではkeep-state、check-stateは未対応だそうです。hoehoeさんより訂正がありました。
[ ログを取る ]
ipfwでファイアウォールのルールを設定できますが、MacOSXは規定ではログオプションをつけてもログを取ってくれません。すぐ後にも出てきますが、sysctlで設定して初めてログが取れるようになります。
では、早速いきましょう。現在のネットワーク構成を知るためにTerminalからifconfigコマンドを叩きます。
[ ifconfig -a ]
----------------------------------------------------------------
[macosx:~] root# ifconfig -a
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
inet 127.0.0.1 netmask 0xff000000
## これはloopbackアドレス
en0: flags=8863<UP,BROADCAST,b6,RUNNING,SIMPLEX,MULTICAST> mtu
1500
inet 192.168.0.10 netmask 0xffffff00 broadcast 192.168.0.255
ether **:**:**:**:**:**
media: autoselect (100baseTX <full-duplex>) status: active
supported media: none autoselect 10baseT/UTP <half-duplex>
10baseT/UTP
<full-duplex> 100baseTX <half-duplex> 100baseTX <full-duplex>
1000baseTX
<full-duplex>
## これがNIC
上記のようになると思います(ウチはNIC1枚しかありません)
もし2枚刺さってたら、さらに下記のような出力が得られると思います。
en1: flags=8863<UP,BROADCAST,b6,RUNNING,SIMPLEX,MULTICAST> mtu
1500
inet 100.100.100.1 netmask 0xffffff00 broadcast 100.100.100.255
ether **:**:**:**:**:**
media: autoselect (100baseTX <full-duplex>) status: active
supported media: none autoselect 10baseT/UTP <half-duplex>
10baseT/UTP
<full-duplex> 100baseTX <half-duplex> 100baseTX <full-duplex>
1000baseTX
<full-duplex>
----------------------------------------------------------------
ここでen1にキチンとIPアドレス(61.122.xxx.xxxや172.24.xxx.xxxなど)が振られていればOKです。もし「169.254.xxx.xxx」であればDHCPサーバーにリクエストの要求がされているにもかかわらず、アドレスが振られていない状況です。気をつけて!!(ケーブルが外れていませんか?ケーブルが刺さっているにもかかわらずこの状態だったら、InternetのISP側のサーバーの設定がおかしいかもしれません。向こうの管理者に電話してみてください。結構よくやりますよローカルなところは)ここまでがIPアドレスの確認です。
次にNATとログ取りを有効にするための設定の内容確認です。これもコマンドでいきましょう 。
[ sysctl -a | more ]
----------------------------------------------------------------
[macosx:~] root# sysctl -a | more
kern.ostype = Darwin
kern.osrelease = 1.4
kern.osrevision = 199506
kern.version = Darwin Kernel Version 1.4:
-中略-
net.inet.ip.forwarding: 0
-中略-
net.inet.ip.fw.verbose: 0
net.inet.ip.fw.verbose_limit: 0
----------------------------------------------------------------
変数の各値が0になっているのを確認します。
[ net.inet.ip.forwarding: 0 ]は複数のネットワークインターフェイスを経由する通信(ルーティング)の許可(1)/不許可(0)を設定する項目です。1になっている場合はルーティングが許可されている状態です。
また、
[ net.inet.ip.fw.verbose: 0 ]を「1」にしてやるとログ採取が有効になり、
[ net.inet.ip.fw.verbose_limit: 0 ]に「100」といれてやれば一つのルール辺り100行までログを取ってくれます。
このsysctlっていうコマンドはカーネルパラメータ表示、設定、変更を簡単に行えるツールです。一度 sysctl -a で全部見てみるのもいいかもしれませんね。ちなみにsysctlで見える「net.inet.ip.forwarding」などはWindowsでいうところのレジストリに当たるものだと考えていただければいいです。つまりコレを下手に直接イジルト・・・。ためしにやってみます?私は怖くて怖くて、よう手が出ません
。
次にservicesファイルの内容の確認です。
[ cat /etc/services | grep natd ]
----------------------------------------------------------------
[macosx:~] root# cat /etc/services | grep natd
natd 8668/divert # Network Address Translation
----------------------------------------------------------------
になっているのを確認。これはnatdというデーモンがポート8668を使うというふうに書いてあります。Apacheは80、Telnetは23、SSHは22などと同じです
。
この2つの記述が無いとかなりヤバイですな 。
ここまでが確認になります。次に実際の設定を行いましょう。いよいよ後半戦に突入です。以前書いたipfw.shファイルをNIC2枚挿し用に変更します。その内容を以下に示します。Desktopにでも作ってください。
尚、このルールはFreeBSDの「防火壁へのルールセット」というドキュメントを基にしています(ていうかほんとそのまんま)
[ ipfw.sh ]
----------------------------------------------------------------
#!/bin/sh
#---------------------------------------#
# en1=インターネット側
# en0=ローカルエリア
#---------------------------------------#
# コマンドとDNS serverのipアドレスをセットする
# ログをとるためsysctlを使う
# ローカルエリアのアドレスも設定
set fw="/sbin/ipfw"
set fwq="/sbin/ipfw -q"
set ns1="xxx.xxx.xxx.xxx"
set ns2="xxx.xxx.xxx.xxx"
set ctl="/usr/sbin/sysctl"
set inet="192.168.0.0/24"
# ログ収集の有効化とサイズを決定
$ctl -w net.inet.ip.fw.verbose=1
$ctl -w net.inet.ip.fw.verbose_limit=1000
# ルールを初期化する
$fw -f flush
# ループバックを設定
# (lo0にくるのは良いが、127.0.0.0/8宛てにくるのはおかしい)
$fwq add accept ip from any to any via lo0
$fwq add drop ip from any to 127.0.0.0/8
# spoofing(私のアドレスを使った)外からのパケットは破棄
$fwq add drop ip from $inet to any in via en1
# NATを有効にする
$fw add divert natd ip from any to any via en1
# 自分が着手した全ての接続を許可
$fwq add accept tcp from any to any out xmit en1 setup
# 接続がいったん作成されると,それを許可して開ける
$fwq add accept tcp from any to any via en1 established
# 公開用serverの設定
$fwq add accept tcp from any to any 80 setup
# 規定されたサーバに対して *のみ* 外部 DNS の問い合わせを許可
$fwq add accept udp from any to $ns1 53 out xmit en1
$fwq add accept udp from any to $ns2 53 out xmit en1
# 応答とともに戻ってくることを許可
$fwq add accept udp from $ns1 53 to any in recv en1
$fwq add accept udp from $ns2 53 to any in recv en1
# keep-state これで動的に穴をあけてくれる。うまくいけばパッシブモード対応だ
$fwq add accept tcp from any to any keep-state out via en1
$fwq add accept udp from any to any keep-state out via en1
$fwq add accept tcp from $inet to any keep-state
$fwq add accept udp from $inet to any keep-state
# ほんで、check-state
$fwq add check-state
### keep-stateとcheck-stateはキープして、チェックする。そのまんま ###
# そのほかのUDPは破棄
$fwq add drop udp from any to any in via en1
# ICMPは許可
$fwq accept icmp from any to any
# 内側のネットワークは許可
$fwq add accept ip from 192.168.0.0/24 to any via en0
# 最後は全て破棄してログを取る
$fwq drop log ip from any to any
# カウンタをゼロにする
$fw zero
----------------------------------------------------------------
ここまで出来たら、
%sudo cp ./Desktop/ipfw.sh /usr/local/sbin/
Desktopからcopyして、OS起動時に立ち上がるようにStartupItemsにディレクトリIPFWを登録。さらにIPFWファイルとStartupParameters.plistを作成。
[macosx:~] root# ls /Library/StartupItems/
IPFW Samba
[macosx:~] root#
以下参照。
[IPFW]
----------------------------------------------------------------
#!/bin/sh
##
# Start IPFW
##
. /etc/rc.common
if [ "${IPFW:=-NO-}" = "-YES-" ]; then
ConsoleMessage "Starting IPFW"
/usr/local/sbin/ipfw.sh ### さっきのファイルを指定 ###
/usr/sbin/natd -n en1 ### この行を追加。NATを起動します ###
fi
[EOF]
----------------------------------------------------------------
[StartipParameters.plist]
----------------------------------------------------------------
{
Description = "IPFW";
Provides = ("IPFW");
Requires = ("Disks","Network");
OrderPreference = "None";
Messages =
{
start = "Starting IPFW";
stop = "Stopping IPFW";
};
}
[EOF]
----------------------------------------------------------------
さらにhostconfigファイルを編集します
[hostconfig]
----------------------------------------------------------------
##
# /etc/hostconfig
##
# This file is maintained by the system control panels
##
# Network configuration
HOSTNAME=g4
ROUTER=-AUTOMATIC-
# Services
AFPSERVER=-NO-
APPLETALK=-NO-
AUTHSERVER=-NO-
AUTOMOUNT=-YES-
CONFIGSERVER=-NO-
IPFORWARDING=-YES-
### 規定ではNOになっていますが、IPFORWARDINGをYESに変えます
### ここで [ net.inet.ip.forwarding ] パラメータを1にしています
MAILSERVER=-NO-
MANAGEMENTSERVER=-NO-
NETINFOSERVER=-AUTOMATIC-
RPCSERVER=-AUTOMATIC-
NETBOOTSERVER=-NO-
NISDOMAIN=-NO-
TIMESYNC=-NO-
QTSSERVER=-NO-
SSHSERVER=-YES-
WEBSERVER=-YES-
SMBSERVER=-YES-
IPFW=-YES-
### 上の1行を追加(これが無いと[ .plist ]ファイルが参照しにいけない)
[EOF]
----------------------------------------------------------------
確認は
[macosx:~] root# sudo /sbin/SystemStarter
で確認してください。
これで、(たぶん)WebServiceのアクセス以外(一部DNS含む)は防ぐことが出来るかと思います。確信が持てない場合は(私も確信がありません)、nmapなどでポートスキャンをしてみてきちんとブロックできるかどうかを確かめてください。次回は番外編です。
- Mac OS Xで作るファイアウォール番外編[ TcpWrapperとの違い ] -
はじめに:
TcpWrapperとipfwの違いを見てみようと思ったのですが、かなり長くなってしまいました。
nmap,TcpWrapper,ipfwの基本的な使い方は各マニュアル(man)を参照してください(BSDと同じです)
1.TcpWrapperなし、ipfwなし
2.TcpWrapperのみ
3.ipfwのファイアウォール
という構成で見ていきますね
注意)
MacOSX10.1以降ではTelnet-Serviceはデフォルトでは起動していません。しかし、ここでは実験のために起動させています(くれぐれもTelnetは使わないように!またログ収集も行っていません。あしからず)。さらに、Apache-Web共有(httpd)、FTP-Service、SSH、Sambaも起動させておきます
# やり方は、しまケロさんのとこと同じやり方です
### ウチではLinuxの/etc/hostsファイルをいじってありますので、
### 皆さんの環境に合わせてご覧下さい(ip入れるのが面倒くさくて)
nmapを使ってスキャンしてみましょ(ちなみにnmapによるポートスキャンは、すべてLinuxから行われています)
以下参照
まずは、サービスの状態を確認します。
[ lsof -i を実行-MacOSX ]
----------------------------------------------------------------
[g4:/Users/x_user] root# lsof -i
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
syslogd 174 root 4u inet 0x02361f20 0t0 UDP *:syslog
netinfod 202 root 5u inet 0x02361e50 0t0 UDP localhost:1033
netinfod 202 root 6u inet 0x023dbd1c 0t0 TCP localhost:1033 (LISTEN)
netinfod 202 root 7u inet 0x023db50c 0t0 TCP localhost:1033->localhost:812
(ESTABLISHED)
netinfod 202 root 8u inet 0x023d875c 0t0 TCP localhost:1033->localhost:878
(ESTABLISHED)
lookupd 209 root 4u inet 0x023dafac 0t0 TCP localhost:812->localhost:1033
(ESTABLISHED)
smbd 215 root 9u inet 0x023dacfc 0t0 TCP *:netbios-ssn (LISTEN)
nmbd 217 root 6u inet 0x02361d80 0t0 UDP *:netbios-ns
nmbd 217 root 7u inet 0x02361cb0 0t0 UDP *:netbios-dgm
nmbd 217 root 8u inet 0x02361be0 0t0 UDP g4:netbios-ns
nmbd 217 root 9u inet 0x02361b10 0t0 UDP g4:netbios-dgm
inetd 230 root 4u inet 0x023da4ec 0t0 TCP *:ftp (LISTEN)
inetd 230 root 5u inet 0x023da79c 0t0 TCP *:telnet (LISTEN)
inetd 230 root 6u inet 0x023da23c 0t0 TCP *:swat (LISTEN)
automount 248 root 4u inet 0x02361a40 0t0 UDP *:848
httpd 254 root 16u inet 0x023d8f6c 0t0 TCP *:80 (LISTEN)
httpd 256 www 16u inet 0x023d8f6c 0t0 TCP *:80 (LISTEN)
sshd 269 root 3u inet 0x023d9a2c 0t0 TCP *:22 (LISTEN)
loginwind 277 x_user 7u inet 0x023d8a0c 0t0 TCP localhost:878->localhost:1033
(ESTABLISHED)
----------------------------------------------------------------
[ netstat -an も実行-MacOSX ]
----------------------------------------------------------------
[g4:/Users/x_user] root# netstat -an
Some ip sockets may have been created or deleted
Some icmp sockets may have been created or deleted
Some igmp sockets may have been created or deleted
Active Internet connections (including servers)
Proto Recv-Q Send-Q Local Address Foreign Address (state)
tcp 0 0 192.168.0.10.139 192.168.0.1.1032 ESTABLISHED
tcp 0 192 192.168.0.10.22 192.168.0.1.1030 ESTABLISHED
tcp 0 0 127.0.0.1.1033 127.0.0.1.878 ESTABLISHED
tcp 0 0 127.0.0.1.878 127.0.0.1.1033 ESTABLISHED
tcp 0 0 *.22 *.* LISTEN
tcp 0 0 *.80 *.* LISTEN
tcp 0 0 *.901 *.* LISTEN
tcp 0 0 *.23 *.* LISTEN
tcp 0 0 *.21 *.* LISTEN
tcp 0 0 *.139 *.* LISTEN
tcp 0 60 127.0.0.1.1033 127.0.0.1.812 ESTABLISHED
tcp 0 0 127.0.0.1.812 127.0.0.1.1033 ESTABLISHED
tcp 0 0 127.0.0.1.1033 *.* LISTEN
-- 以下省略 --
----------------------------------------------------------------
こんだけ起動してます
1.TcpWrapperなし、ipfwなし
# nmap 1-Linux #
----------------------------------------------------------------
[root@rh ln]# nmap g4
Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
Interesting ports on g4 (192.168.0.10):
(The 1536 ports scanned but not shown below are in state: closed)
Port State Service
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
80/tcp open http
139/tcp open netbios-ssn
901/tcp open samba-swat
Nmap run completed -- 1 IP address (1 host up) scanned in 1 second
### さらに、-v -sA -p 23 とオプションをつけてみる。 ###
[root@rh ln]# nmap -v -sA -p 23 g4
Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
The 1 scanned port on g4 (192.168.0.10) is: UNfiltered
Nmap run completed -- 1 IP address (1 host up) scanned in 0 seconds
[root@rh ln]#
----------------------------------------------------------------
「The 1 scanned port on g4 (192.168.0.10) is: UNfiltered」という行に注意してください。フィルタがかかっていないというメッセージが帰ってきています。これでフィルタリングがされているかどうか知ることが出来ますね
ここまでは、当然ともいえる結果ですので、賢明な皆様はお分かりになっていただけるかと思います。
2.TcpWrapperのみ
つづいて、TcpWrpperでアクセス制御をかけてみましょう。あらかじめ、hosts.allow/hosts.denyを設定しておきます
[ hosts.allow ]
----------------------------------------------------------------
[g4:/etc] root# cat hosts.allow
ALL:192.168.0.10/255.255.255.0:allow
sshd:ALL:allow
ftpd:ALL:allow
----------------------------------------------------------------
[hosts.deny]
----------------------------------------------------------------
[g4:/etc] root# cat hosts.deny
ALL:ALL
----------------------------------------------------------------
設定が出来たら、inetdのプロセスを再起動してスキャンしてみます。
プロセスを再起動は、[ ps ax | grep inetd ] -> [ kill -HUP <inetdのpid>
]
# nmap 2-Linux #
----------------------------------------------------------------
[root@rh ln]# nmap -v g4
Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
No tcp,udp, or ICMP scantype specified, assuming vanilla tcp connect()
scan. Use -sP if you really don't want to portscan (and just want to
see what hosts are up).
Host g4 (192.168.0.10) appears to be up ... good.
Initiating Connect() Scan against g4 (192.168.0.10)
Adding TCP port 139 (state open).
Adding TCP port 23 (state open).
Adding TCP port 901 (state open).
Adding TCP port 80 (state open).
Adding TCP port 21 (state open).
Adding TCP port 22 (state open).
The Connect() Scan took 1 second to scan 1542 ports.
Interesting ports on g4 (192.168.0.10):
(The 1536 ports scanned but not shown below are in state: closed)
Port State Service
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
80/tcp open http
139/tcp open netbios-ssn
901/tcp open samba-swat
Nmap run completed -- 1 IP address (1 host up) scanned in 1 second
[root@rh ln]#
----------------------------------------------------------------
TcpWrapperでアクセス制御はできますが、ポートを塞いだりすることまでは出来ません!ポートを塞ぐにはファイアウォールで適切にフィルタリングしましょう。
TcpWrapperはinetdプロセス経由で起動してくるデーモン(サービス)に対して「のみ」有効ですが、スタンダードアロンで立ち上げてくるサービス(例えば、SambaやApache,Squidなどその他諸々のアプリケーション)に対しては、一切関知しません。
また、中身を偽造して送られてきたパケットに対しても無力ですし、xinetdのように細かく設定することすら出来ません。アクセス制御機能=ファイアウォールではないのです。
3.ipfwのファイアウォール
で、まぁ余計な穴は塞ぐ事にしましょうか(もうお馴染みですね! ipfwを使います)。今回は簡単なルールで検証して見ましょう。
[ ipfw.sh ]
----------------------------------------------------------------
#!/bin/tcsh
set fw="/sbin/ipfw"
# 初期化
$fw -f flush
# ローカルホストはOK!
$fw -q add accept ip from any to any via lo0
$fw -q add accept ip from 192.168.0.10 to any via en0
# 接続確立したものはOK!
$fw -q add accept tcp from any to any out xmit en0 setup
$fw -q add accept tcp from any to any via en0 established
# 接続を確立しようとするものはOK!
$fw -q add accept tcp from any to any 80 setup
$fw -q add accept tcp from any to any 22 setup
$fw -q add accept tcp from any to any 21 setup
# icmpはOK,TelnetはNG,その他のパケットは破棄
$fw -q add accept icmp from any to any
$fw -q add drop tcp from any to any 23
$fw -q add drop ip from any to any
# カウンタをゼロにする
$fw zero
----------------------------------------------------------------
コイツを実行してから、もう一度nmapでスキャンしてみると・・・
# nmap 3-Linux #
----------------------------------------------------------------
[root@rh ln]# nmap g4
Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
Interesting ports on g4 (192.168.0.10):
(The 1539 ports scanned but not shown below are in state: filtered)
Port State Service
21/tcp open ftp
22/tcp open ssh
80/tcp open http
Nmap run completed -- 1 IP address (1 host up) scanned in 159 seconds
### httpとftp、sshのみが外部に対して公開されているかのように見えます。 ###
### Telnetに対してスキャンしてみましょう。 ###
[root@rh ln]# nmap -v -sT -p 23 g4
Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
Host g4 (192.168.0.10) appears to be up ... good.
Initiating Connect() Scan against g4 (192.168.0.10)
The Connect() Scan took 2 seconds to scan 1 ports.
Interesting ports on g4 (192.168.0.10):
Port State Service
23/tcp filtered telnet
Nmap run completed -- 1 IP address (1 host up) scanned in 2 seconds
### フィルタリングされていることが確認できます。しかし・・・ ###
[root@rh ln]# nmap -v -sF -p 23 -g 53 g4
Starting nmap V. 2.54BETA22 ( www.insecure.org/nmap/ )
Host g4 (192.168.0.10) appears to be up ... good.
Initiating FIN Scan against g4 (192.168.0.10)
The FIN Scan took 1 second to scan 1 ports.
Interesting ports on g4 (192.168.0.10):
Port State Service
23/tcp open telnet
Nmap run completed -- 1 IP address (1 host up) scanned in 1 second
[root@rh ln]#
----------------------------------------------------------------
ここで、Telnetサービスが起動しているのが分かってしまいます(T_T)
どうしたらいいかという事になるのですが、個人的には以下のようなルールを入れてログを取っておけばいいと思います。
ipfw add drop log tcp from any 20,21,23,25,80,110 to any 20,21,23,25,80,110
in via en1
要は、送信元ポート番号が20,21,23,25,80,110で、宛先ポート番号も20,21,23,25,80,110というとっても怪しいパケットはログにとって残しておくってこと
余談)
*** こういったパケットをtcpdumpで解析してみると、結構面白いですよ ***
ここで注意するべきことは、ipfwはホストに対して送られてくるパケットを「許可」するか「拒否」するか「破棄」するかのどれか『しかしない』ということです。許可されていれば、IPデータグラム(パケット)のデータ部の中身によらず、たとえウィルスであろうとなかろうとあて先のホストまで届けようとしますし、拒否であれば、届かなかったことを送信元のホストへ通知します。破棄であるならばパケットをそのように処理し、送信元への通知もしません。
さらに、ファイアウォールといえども脆弱性を突いた攻撃までは防げません。ウィルスに対しても無力です。また、ログに残るという点にも注意が必要です。ログへの書き出しはパケットを受け取った、もしくは破棄した時点で書き込まれ、自分で確認しない限りホストの状況を把握することが出来ません。つまり、リアルタイム性がないのです。そればかりか、インターネットに公開しようとするサービスは、その(公開しようとする)アプリケーション・レベルで保護しなければなりません。自分でセキュリティホールを作ってしまう可能性の方が高いかもしれません(自作のCGIとかは特に)。
最後に:
これで、多少の違いが分かったかと思います(わかんなかった?)。んで、それはわかったんだけど、実際どうすりゃいいんだ?という疑問が出てくるとありがたいです。それついてはまた色々とあります。例えば、TcpWrapperよりもTcpServerにしてみるとか、IPFWだけでなくSnortでリアルタイム性を確保するとか、それぞれを組み合わせて二重・三重に対策を立てることも可能です。この機会に是非試してみてください。そして私にも教えてください(^_^;
|