ACLをどうにかしたい話

ちょっとやっては飽きたり挫折したり面倒くさくなって放り投げたりしていた企画を今月になってまたやっていました。

……あらためて並べてみると古いねえ。年単位で放置してるし。それをなんでここに来てまたやり始めたかというと、Trema 関係で Ruby でいろいろ書くようになって、Perl で面倒だなあと思っていたところって実は Ruby でやるとわりと障壁下がるんじゃないかなあ…と思ったからでした。あと ACL 何とかしたい(某お仕事的に)というのは変わらないので。やってないから解決したかってそんなことなくて、数年延命しながら崖っぷちにちょっとずつ近づいているだけなのだ。…というACLどうにかしたい話は別なところでまとめたい。とりあえずツールについて今回は書く。

Perl で作ってたとき は基本的な ACL の syntax まではできてたのでコレは流用したらいいよねー。というところで、Racc への移植とアクションを作るって事をやってみたのでした。

とりあえず使ってみる

今のところの機能

ここに置いてある

今のところこの辺の機能が実装できています。

  • Named/Numbered ACL
  • Extended/Standard ACL

名前付き拡張ACLとかで 2×2になるので、主要な4種類の ACL を parse することができます。というより目論見は parse することと言うよりは、読んだ上でアレコレ処理させることなので、ACL Interpreter (ACL Intp) という名前にしてみました。

インストール

bundler で生成しているけど rubygems への登録とかはしてません。というのもまだ大幅に内容を書き換える可能性があると思っているので。そもそもですね。テストとかまだちゃんと網羅的にかけてないのですよ。そこそこ動くよな…というところまでは見えているけど。入れるのはそんなに面倒じゃないはず。git clone して bundle install してください。

Syntax Checker として

とりあえず動かしてみましょうかね。tool/check-acl.rbACL Intp の応用として書いてみたツールです。複数のACLを読み込んで解釈し、同じ物を出力するだけです…ってだけだとあまり実用性がないので、エラーがあればそれを教えてくれます。手書きで書いたACLが正しいかどうかチェックするような使い方を想定した物ですね。term-ansicolor を使って、要素別にカラーリングをしています。

stereocat@vnwt10ctrl-of13:~/cisco_acl_intp$ ruby tool/check-acl.rb -h
ruby tool/check-acl.rb [options] [args]
    -c, --color                      enable coloring
    -d, --debug                      enable debug print
        --yydebug                    enable yydebug
    -f, --file FILE                  acl file
stereocat@vnwt10ctrl-of13:~/cisco_acl_intp$

samples ディレクトリにいくつかACLのサンプルがあります。それを読ませてみましょう。-fオプションでファイルをわたしてもいいし、ファイルオプションがなければ標準入力から読むようになっています。

  • 元ファイル
    • 対応している4種類のACLを書いてあります。
    • ACL にはいくつかエラーが埋め込んであります。エラーがある行の前後には remark をつけてあります。
stereocat@vnwt10ctrl-of13:~/cisco_acl_intp$ cat samples/err-acl.txt
access-list 1 permit 192.168.0.0 0.0.255.255
access-list 1 deny   any log
access-list 100 remark General Internet Access
access-list 100 permit icmp any any
access-list 100 permit ip 192.168.0.0 0.0.255.255 any
access-list 100 permit tcp any host 210.197.74.200
access-list 100 remark !wrong acl number!
access-list 10 permit udp any eq ntp any eq ntp
access-list 100 remark !------cleared------!
access-list 100 remark !wrong header! caccess-list
caccess-list 100 remark 6to4
access-list 100 remark !------cleared------!
access-list 100 permit 41 any host 192.88.99.1
access-list 100 remark !wrong ip proto number!
access-list 100 permit 256 any host 192.88.99.1
access-list 100 remark !------cleared------!
access-list 100 remark !wrong ip proto!
access-list 100 permit hoge any host 192.88.99.1
access-list 100 remark !------cleared------!
access-list 100 permit ip any host 192.88.99.1
access-list 100 remark others
access-list 100 permit tcp any eq 0 any eq 0
access-list 100 permit udp any eq 0 any eq 0
access-list 100 deny   ip any any log
access-list 110 remark SPLIT_VPN
access-list 110 permit ip 192.168.0.0 0.0.255.255 any

ip access-list extended FA8-OUT
deny   udp any any eq bootpc
deny   udp any any eq bootps
remark !argment error! 65536
permit tcp host 192.168.3.4 173.30.240.0 0.0.0.255 range 32768 65536
remark !------cleared------!
remark !argment error! 255 => 256
deny udp 192.168.3.0 0.0.240.256 lt 1024 any eq 80
remark !------cleared------!
remark network access-list remark!!
permit tcp any any established
deny tcp any any syn rst
remark !syntax error! tcp -> tp (typo)
deny up any any log-input hoge
remark !------cleared------!
permit ip any any log
!
ip access-list standard remote-ipv4
permit 192.168.0.0 0.0.255.255
remark standard access-list last deny!?
deny   any log
!
stereocat@vnwt10ctrl-of13:~/cisco_acl_intp$

実行してみるとこんな感じ。

いま、Parser 上のエラー処理(エラーリカバリ)は行単位なので、

  • エラーがあればその行は捨てる
  • 1行に複数のエラーがある場合は、エラー判定できるのは最初に見つかった物だけ

です。ということで、元ファイルのエラー行が消えて、前後の remark 行だけが出てくれてれば正解、ということ。見つかったエラーは上の方にわらわらっと出てます。

機能と制限

もともとやりたいことってなんだって、別に ACL syntax check だけじゃないわけですね。ACL を読んで object 化された上で各種処理を加えられるようになりたい。コード観てもらえればわかりますが、読み込み終わった時点で ACL class object が帰ってくるようになってるので、後はそのオブジェクトに対して検索処理とかいろいろ実装したいわけです。まあそれも今後のネタということで。

で、そういった構造上の都合なども含めてまだいくつか機能制約があったりします。

  • Named ACL のヘッダ部分(1行目の ip access-list の行でのエラー処理
    • ACL object に対してエントリ追加していく構造なので、名前付き ACL の1行目にエラーがあるとその ACL そのものを処理できなくなっちゃう(エントリを追加する対象が作れない)。Numbered ACL だったら1行ごとに全部「名前(番号)」がついてるからわかるんだけどね。

そもそもまだ実装していない機能

  • syntax としては object-group とかかなりマニアックな機能についても実装してありますが、その辺はやってません。というか自分が普段使っている(使ったことがある)物だけ今は実装しています。このあたりは時間があれば拡張していく…かな……
  • eq 80 443 8000 8080 みたいに eq/neq が複数(10個まで)のポート番号リストを取るみたいな機能も新しい IOS だとあるみたいだけど、これはまだ syntax そのものの実装ができていません。…こういう機能っていつついたんだろう? 手元でチェックするように使っていたのが IOS 12.2(52) くらいなので、基準はこの辺です。
    • ACL の feature の全貌がよくわからん…。全 feature に対してどのくらい実装してるかみたいなの調べたいんですが、まあ面倒でね…
  • IPv6 ACL には対応していません。
  • PIX/ASA 系の ACL には対応していません。

まとめ

なんかとりとめのない話ですが。まあ最近こういうのを作ってて、それっぽく動くところまでできたので軽く紹介だけしてみようかなあってだけです。テストもうちょっと真面目に作らないと…と思いつつ、コレを使った応用ってところで今ちょっと考えているのでいったんコレの実装はペンディング。まあまたどっかで手をつけるでしょう。