Cisco PIX/ASA の MSS に関連するトラブル

ネットワークトラブルの中で、特に嫌なものは MTU や MSS 関連のトラブルです。 この手のトラブルでは、同じ相手に同じ通信アプリケーションを使っていても、通信ができたりできなかったりするような現象が見られます。再現性がなさそうにみえるので、思わず「パソコンをリブートして様子をみてください」と言いたくなってしまうのですが、それでは何の解決にもなりません。 覚悟を決めてパケットキャプチャーしてみると特定のサイズのパケットだけ届いていないというような現象が判明し、冷や汗をかくことになるわけです。

さて身近なところで Cisco PIX/ASA に関連して MSS のトラブルが起こりました。 詳細はこちらの URL にある通りなのですが、要約すると以下のようなものです。

  • クライアントが通知した MSS を超えるセグメント長となるパケットがサーバ側から到達したため、ASA がドロップした
  • サーバに手を入れられない場合、有効な workaround は、MSS のチェックを無効にすること

根本の問題は通知した MSS を無視するようなサーバの存在ですね。 ASA はこのようなサーバからのパケットを不正なパケットと判断してドロップしてしまったわけです。 Software Version 7.0 からデフォルトの動作がこのようになりました。

通信できるようにするという観点では、先の URL にあるような設定を入れて MSS チェックを無効化すればよいですが、 お客様/社内のしかるべき責任者へこの設定変更内容をきちんと説明できなければなりません。 TCP に明るくない方へ説明する時に、「MSS とは」というところから始めると下手すると細かい話ばかりになって何を説明しているのかわからなくなってしまいます。 以下の点をうまく説明できると良いですね。

  1. そもそも、クライアントの通知した MSS を無視するようなタコな実装のサーバが悪い。
  2. そのサーバとの通信を許可するためには PIX/ASA の MSS チェックを無効化しなければならない。
  3. 確かにセキュリティレベルという観点からするとチェックをしなくなるのでレベルは落ちるが、実際問題としてイマドキの端末ならばこのようなパケットによりバッファーオーバーフロー等の問題を起こすようなタコな実装はしていない。 従って事実上チェックを無効化するリスクは小さい。

1. と 3. が矛盾するような気がちょっとだけしますが…

Cisco PIX/ASA: most used、RPF

Cisco ASA/PIX の小ネタです。ソフトウェアバージョン 7.X、6.X を想定しています。

"most used" とは?

Cisco ASA/PIX でコネクションテーブルを見るのは "show conn"、NAT テーブルは "show xlate" です。これらの出力結果には "most used" というカウンター値が表示されています。下の例で言えば "10" がそうです。

fw# show conn
2 in use, 10 most used
(… 略)

恥ずかしながら実はこれが何のことかすぐにはわからなかったです(汗)。言われてみればその通りなのですが、これまでの最大コネクション数 (最大 NAT エントリ数) ですね。それはさておき、これらのテーブルのチェックに加えて "show access-list" でヒットカウンターを見るのと、先日紹介した capture コマンドで大部分の問題判別はできると思います。

Reverse Path Forwarding

Reverse Path Forwarding (RPF) とはルーティングテーブルとパケットのソースアドレスを照合して不適切なインターフェイスより届いたパケットをドロップするものです。FireWall-1 ではトポロジを設定して Anti-Spoof させますがそれと似たようなものですね。以下のようにインターフェイスを指定して ip verify reverse-path コマンドを実行することで機能が有効になります。

ip verify reverse-path interface outside

outside 側にはデフォルトルートが設定されているケースが多いと思いますが、その場合でも outside インターフェイスに RPF をかければ、内部アドレスをソースにしたパケットを落とすことができます。もちろん外部側のアドレスで Spoofing されたパケットが outside インターフェイスに届いた場合はどうしようもないのですが、そこは手動で Ingress フィルターを追加する手間を省くための機能ということで理解しましょう。

inside インターフェイスにかければ内部ルートとしてルーティングテーブルに載っているアドレスからのパケットのみを通すようになります。

結構 Cisco PIX/ASA に関する blog エントリが増えたので、ここらで一覧にまとめておきます。

「これが趣味なの?」って感じでしょうが、備忘録としてのブログなのでそこはご容赦を。


2007. 2. 16 追記:

×「most in used」→○「most used」です。訂正しました。何だかボケてます。

Cisco PIX/ASA ACL に関する小ネタ

Cisco PIX/ASA の小ネタをいくつか書きます。対象ソフトウエアバージョンは特に断りなければ 6.X、7.X です。

permit のログが出ない?

「access-list コマンドで log オプションをつけたら、 deny されたログは出るんだけれど permit のログが出ないなあ」なんて思った経験はありませんか? access-list の log オプションはレベルを指定しなければ informational (=6) で出力されるので logging コマンドでこれ以上のレベルを指定しなければなりません。

logging buffered informational (内部バッファ用)
logging trap informational (SYSLOG 用)

レベルを適切に設定しなければならないのは deny の場合も同じですが、以下のようなところから permit だけログが出ていないように思えてしまうようです。(経験に基づいています)

  • access-list コマンドで log オプションをつけていないデフォルトの状態では、deny のログだけ出力される。(ちなみにこの時のメッセージ番号 は 106023 で warnings レベル。log オプションをつけた時はメッセージ番号 106100 で出力されます。)
  • 他の理由で deny されたログを見て、permit だけ出ていないように思ってしまう。

ACE (Access Control Entry) をまとめて追加

Cisco の PIX/ASA には PDM やら ADSM やらという GUI がついています。しかし、私の触ったバージョンを見る限りでは access-list (ACL) 編集機能が今一つなので結局これらのツールは使用せず、 ACL はコマンドラインで直しています。コマンドラインで以下のように ACL の途中にまとめて行(ACE)を挿入したいとき何も考えずにそのまままとめてコピー&ペースト等で入力するといくつかの ACE でエラーが起きたとき順番が狂って大変なことになります。この場合一旦エラーが起きた以降の ACE を全部消してから入れ直さなければなりません。エディタで編集してターミナルエミュレータにコピー&ペーストなんてときにありがちですね。

access-list MYLIST line 10 extended permit tcp host 192.168.0.10 any eq telnet
access-list MYLIST line 11 extended permit tcp host 192.168.0.11 any eq ssh
access-list MYLIST line 12 extended permit tcp host 192.168.0.12 any eq sqlnet

やっている人も多いと思いますが、この時次のように逆順に並べて入力すればエラーが起きたときのダメージを最低限にすることができます。

access-list MYLIST line 10 extended permit tcp host 192.168.0.12 any eq sqlnet
access-list MYLIST line 10 extended permit tcp host 192.168.0.11 any eq ssh
access-list MYLIST line 10 extended permit tcp host 192.168.0.10 any eq telnet

そこで、まとまった量の ACE をコピー&ペーストするために逆順に並べるのにどうしたら楽か検討したのですが、

perl -e 'print reverse <>;'

っていうのを覚えました。結構 perl の一行ものは重宝しますね。

PIX には全然関係ないですが、以前はシェルスクリプト中で昨日の日付を求めるのに、

perl -e 'use POSIX qw(strftime); print strftime "%Y%m%d\n", localtime(time - 3600*24);'

というのをよく使いました。OS 標準の date コマンドではできないことが多いのでこれも重宝しました。


外側インターフェイスへの ping

マニュアルの記述だとわかりにくいところもありますが、デフォルトでは外側から外のインターフェイスに対して ping をかけると応答があります。これを防ぐには以下のコマンドを入力します。

icmp deny any outside

これで deny されるのはインターフェイスのアドレスに対しての ICMP メッセージのみです。ファイアーウォールの内側に存在するアドレスに対しての ICMP メッセージの制御は access-list コマンドで実行します。

Cisco PIX/ASA の NAT: アドレス空間を完全に分ける

Cisco の PIX/ASA ファイアーウォールの NAT に関してマニュアル等に例としてよく出てくるのは、インターネット (グローバルアドレス) と社内 (プライベートアドレス) の間の通信でプライベートアドレスは当然インターネット側に流れないけれど、社内にグローバルアドレスは入ってくるという NAT の例です。しかし、社内からグローバルアドレスを排除しプライベートアドレスのみ流すようアドレス空間を完全に分けてしまいたい時があります場合もあります。この時に static NAT を設定する方法を備忘録としてまとめます。完全にアドレス空間を分けたいのはインターネット接続よりもグループ企業間接続の場合などでしょうが、説明は社内 (プライベートアドレス)/社外 (グローバルアドレス) と想定して説明します。

社内の 192.168.0.1 というコンピュータAが社外の 1.1.1.1 というコンピュータBと通信することを想定します。それぞれ NAT 用に 1.1.1.10 と 192.168.0.10 というアドレスを用意します。 private IP address 192.168.0.1 を global IP address 1.1.1.10 にマップするには以下のコマンドを打てとマニュアルにあります。

static (inside,outside) 1.1.1.10 192.168.0.1

これで、

社内→社外のパケットの source IP address と
社外→社内のパケットの destination IP address

が変換処理の対象になります。ところで、例えば社外のコンピュータBから 1.1.1.10 に telnet した場合、通信が許可されていればコンピュータAに telnet することができます。この段階では、コンピュータAからはBの実アドレス 1.1.1.1 からの通信に見えます。これを 192.168.0.10 からの通信に見えるようにするためには、

static (outside,inside) 192.168.0.10 1.1.1.1

と実行します。すると

社内→社外のパケットの destination IP address と
社外→社内のパケットの source IP address

も変換処理対象になります。これで完全にアドレスを分割することができました。ACL は適用するインターフェイスが inside ならば内側のアドレス空間で、 outside ならば外側のアドレス空間を用いて書きます。

Cisco PIX/ASA で NAT 変換を行わない設定

ソフトウェアバージョン 7.0 より NAT が不要の場合は nat, static 等のコマンドを全く書く必要がなくなりました。6.x 台では NAT を使わない時でも NAT 関連のコマンドを設定しなければならず、例えば、

(inside -> outside 用)
nat (inside) 0 10.0.0.0 255.0.0.0
(outside -> inside 用)
static (inside,outside) 10.0.0.0 10.0.0.0 netmask 255.0.0.0

のようなコマンドを設定しておかなければなりませんでした。何でこんな設定を入れなければならないのー、と思っていましたが、これが 7.0 より全く不要になります。

もし、昔の挙動との互換性のために、通信を通すには NAT ルールが必須としたいのであれば、

nat-control 

と入力します。すると NAT を使わないときも 6.x 台と同様のルールが必要になります。互換性以外にこれを設定する理由はないでしょうね。


2007.9.13 追記
「互換性以外にこれを設定する理由はないでしょうね」と書きましたが、site-to-site VPN の設定で余計なトラフィックを遮断する時は nat-control を入力して済ませた方が楽かも知れません。この記事のコメントを書いていて気づきました。

PIX/ASA の policy-map

備忘録を兼ねる Cisco PIX/ASA の設定情報です。

ICMP の扱い

以前は ping を通すために双方向に ICMP を許可する ACL を設定しなければなりませんでしたが、PIX 7.x 台より ICMP のステートを見るようになっています。すなわち片方向に ICMP 許可 ACL を設定すれば許された方向に ping をかけることができるようになります。

デフォルトでは ICMP の検査は有効でないので、policy-map で “inspect icmp” と設定する必要があります。初期設定を元にした場合は以下のように設定します。

FW(config)# policy-map global_policy
FW(config-pmap)# class inspection_default
FW(config-pmap-c)# inspect icmp

修正された policy-map の全体は次のセクションを参考にしてください。

UDP の扱い

多くのファイアーウォールと同様、UDP は擬似コネクションとして扱いステートフルインスペクションの対象となります。デフォルトではタイムアウトにより戻りパケットのポートを閉じる動作ですが、定義済みプロトコルについてはアプリケーション層の内容に基づきより厳しい検査を実施することができます。

例えば SNMP を検査するためには SNMP を識別する class-map を作って使用している policy-map に含める必要があります。具体的には次のような設定となります。先の ICMP と同様初期に自動で出来る policy-map では SNMP の検査は有効でありません。この辺りの設定は以前は fixup コマンドを用いましたが 7.0 よりこのような設定にガラリと変わっています。

class-map snmp
match port udp range snmp snmptrap
class-map inspection_default
match default-inspection-traffic
!
!
policy-map global_policy
class inspection_default
inspect dns maximum-length 512
inspect ftp
inspect h323 h225
inspect h323 ras
inspect rsh
inspect rtsp
inspect esmtp
inspect sqlnet
inspect skinny
inspect sunrpc
inspect xdmcp
inspect sip
inspect netbios
inspect tftp
inspect icmp
class snmp
inspect snmp
!
service-policy global_policy global

IP の access-list

access-list ACLNAME extended permit ip ...

と書くことができます。これだと一見アクセス制御をするのに IP 層までしか検査しないように見えます。しかし、実際はコネクション (ICMP/UDP 等の擬似コネクションを含む) の状態を検査するので、それぞれのプロトコルに応じた検査がなされます。

結局 ACL はコネクションの最初のパケットの通過可否を判断するためにのみ使われ、コネクションが確立された後は保持しているコネクションの状態と通過するパケットの整合性を基に通過可否が判断されるのです。ですので、ルータと同じように access-list を IP で書けば IP 層のチェックのみで通信を通過させることができるわけではないので注意が必要です。

そうそう 7.x からは inbound にも outbound にも ACL を適用できるようになっています。

Cisco ASA でパケットキャプチャー

最近続いている Cisco ASA/PIX の話です。ファイアーウォールの設定は完璧にしたはずなのに、「うまく動かない…」ということがたまにあります。その性質上何か問題が起こるとまず真っ先に「ファイアーウォールで止めてんじゃないの?」と疑われてしまう立場にあります。

ルールの書き間違いならばログを見れば大体わかりますが、ログを見てもわからない場合 ASA/PIX ではパケットをキャプチャーすることができます。

まず、キャプチャーしたいパケットを選別するための access-list (ACL) を作ります。これは問題判別に使うためのパケットを引っ掛けるためだけにファイアーウォールのルールとは独立した ACL を作れば良いです。

例えば、192.168.1.2 宛の通信がおかしければこんな風にします。

fw(config)# access-list mylist extended permit ip host 192.168.1.2 10.0.0.0 255.0.0.0
fw(config)# access-list mylist extended permit ip 10.0.0.0 255.0.0.0 host 192.168.1.2

そしてこの ACL とインターフェイスを指定してキャプチャーを開始します。

fw# capture mycap access-list mylist interface inside

ACL に適合するパケットがインターフェイスを通過すればキャプチャーされます。

fw# show capture
capture mycap type raw-data access-list mylist interface inside[Capturing - 1008 bytes]

キャプチャーできたのであれば詳細を見てみましょう。

fw# show capture mycap
12 packets captured
1: 15:53:16.278839 802.1Q vlan#128 P0 192.168.1.2 > 10.1.2.3: icmp: echo request
2: 15:53:16.279282 802.1Q vlan#128 P0 10.1.2.3 > 192.168.1.2: icmp: echo reply
3: (...略) 

キャプチャーを終了するには次のコマンドです。

fw# no capture mycap

私の経験ではこうして調べて見ると実はファイアーウォール以外に問題があった、ということもよくあります。これらのコマンドを覚えておくといざという時手際よく問題判別ができると思います。

Cisco PIX/ASA の transparent mode

このところ触る機会が多い Cisco PIX/ASA の話です。Cisco ASA 5500 シリーズ (software version 7.0) の transparent mode を利用する機会がありました。transparent mode は通常の L3 IP forwarding でなく L2 で bridging をする動作モードです。このモードで動作している ASA を Spanning Tree Protocol (STP) が通過するように設定しなければならなかったのですが、これにハマってしまいました。


以下のコマンドで transparent mode での動作となります。


firewall transparent


デフォルトの設定では STP のフレーム (BPDU) は通過しないので ethertype を指定した ACL を inside/outside の両方のインターフェイスに明示的に適用しなければなりません。今回は特に ethertype は制限せず、全て通過するよう any を用いて ACL を作りました。


access-list Ethertypes ethertype permit any
access-group Ethertypes in interface inside
access-group Ethertypes in interface outside


これでうまくいくと思ったのですが、何故かツリーが構成されず、内側と外側で別々の root bridge ができてしまいます。


で結局何が悪かったかというと、物理インターフェイスをそのまま使っていたのがまずかったのです。うまく行かないときは次のように設定していました。


interface Ethernet0/0
speed 100
duplex full
nameif inside
security-level 100
!
interface Ethernet0/1
speed 100
duplex full
nameif outside
security-level 0


実は transparent mode ではサブインターフェイスを使わなければならないのです。次のように設定し直すとうまくいきました。


interface Ethernet0/0
speed 100
duplex full
no nameif
no security-level
!
interface Ethernet0/0.1
vlan 100
nameif inside
security-level 100
!
interface Ethernet0/1
speed 100
duplex full
no nameif
no security-level
!
interface Ethernet0/1.1
vlan 101
nameif outside
security-level 0


inside/outside で別々の VLAN 番号を振らなければなりません。このとき 802.1Q が使われるので、ASA が接続する inside 側のスイッチのインターフェイスは次のような設定になります。


(Catalyst 3550 の例)
interface GigabitEthernet0/1
switchport trunk encapsulation dot1q
switchport trunk allowed vlan 100
switchport mode trunk
no ip address
no cdp enable


物理インターフェイスを使っていた場合でも TCP/IP の ACL による制御機能は普通に動いてしまうのでハマりました。知っていれば何てことないのですが、transparent mode ではサブインターフェイスでの設定が必須ということで。

追記 (2007.9.11)

Cisco の Web サイトの設定例を見ると特に BPDU を通すためにはサブインターフェイスの設定が必要とは書かれていないですね。私の試した 7.0 では NG だったのですが、バージョンによるものかも知れないです。

最近は Cisco のサイトの設定例 (Configuration Examples and TechNotes) が充実してきているのでまずここを探すと良いと思います。

さらに追記 以下のバージョン以降はサブインターフェイス不要のようです。
7.0(6.26)、7.1(2.46)、7.2(2.14)、8.0(0.223)、8.2(0.7)

Cisco Adaptive Security Appliance Software Version 7

ここ1、2ヶ月は Cisco のファイアーウォール関連の仕事が続いています。Cisco ファイアーウォール製品 (PIX/ASA) の OS の最新バージョンが 7.X 台になりましたが、6.X 台と比べて多くのコマンドが変わりました。


「げっ、いままでの設定がそのまま入らないよ…。やばっ。」


というわけで慌てて調べたのですが、その成果をまとめておきます。今回は既存のシンプルなファイアーウォールの設定を古い機器& OS から新しく導入する ASA (Software Ver. 7.0) に移行したのですが、設定がシンプルと言えどコマンド変更の影響を受けました。工場出荷時デフォルト設定でも新コマンドがいくつか含まれているのです。以下私の場合に関連した変更点です。
・インターフェイスの設定方法の変更
Cisco ルータのようにインターフェイスコンフィグレーションモードに移行してから設定するようになりました。


interface Ethernet0/1
nameif inside
security-level 100
ip address 192.168.0.1 255.255.255.0
!


というような感じです。IOS のコマンドに合わせたということですね。
・access-list のクリア方法が変わった
access-list を消去するのに “clear configure access-list” コマンドを使うようになりました。一瞬消すコマンドがわからず焦りました。ちなみに1行だけ消すのは “no access-list” コマンドですね。
・fixup コマンドが inspect コマンドに変更
fixuup コマンドが inspect コマンド (+ Modular Policy Framework = MPF) に置き換わりました。とりあえず CLI で fixup コマンドを入力すれば受け付けて MPF のコマンド群に変換してくれるので、fixup コマンドを入力し結果を確認しましょう。変換後は以下のような感じになります。


class-map inspection_default
match default-inspection-traffic
!
policy-map global_policy
class inspection_default
inspect ftp
inspect http
(…)
!
service-policy global_policy global
・新コマンド “ftp mode passive”
アプライアンスの FTP クライアントの動作を指定します。ファイアーウォールの動作には関係ないです。デフォルトの設定で有効化されていました。
・新コマンド dns-guard
DNS Guard は DNS リクエストのヘッダ中の identification field を、レスポンスのヘッダとマッチさせて 1 query に対し 1 response のみ通信を許可する機能です。これもデフォルト設定では有効になっています。
・新コマンド “asdm image”
ASDM (Adaptive Security Device Manager) イメージ、すなわち管理用 GUI を用いるためのソフトウェアの位置を指定するためのコマンド。このコマンドが startup configuration に指定されていなければ、デフォルトの規則に従いイメージを見つけます。ASDM の初回実行後にこのコマンドが自動で追加設定されました。


ちなみに ASDM にアクセスするためには http コマンドで設定を行います。


http server enable
http 192.168.0.0 255.255.255.0 inside


準備ができたら、HTTPS プロトコル (ポートは普通に 443) でアクセスします。その後指示に従い Java のアプレットとして ASDM を実行するか、Launcher プログラムを手許の PC にインストールし、これを用いて起動します。
・conduit/outbound コマンドがなくなった
既になくなることはアナウンスされていましたが、とうとう conduit/outbound コマンドが使えなくなりました。って言っても使っている人は少ないかも知れませんね。私の最初に見た PIX の設定ではこれらのコマンドが使われていて「ふーん。PIX ってよくわかんねえなあ。」というのが第一印象でした。
・”logging on” が “logging enable” に変更


・”floodguard enable” の指定は機能が常時有効化されたので、不要となった
シンプルなファイアーウォールとしての設定を移行するだけでも、これだけの変更が関連しました。VPN 関連も変更があるようなので、関係する人は Upgrade Guide に目を通しておいた方が良いと思います。