Aruba 2530 でループ検知、ブロードキャストストーム検知を試した話

Arubga 2530 というお手頃スイッチがあります。 その中でも 48G (J9775A) でループ検知とブロードキャストストーム検知を試したのでそのメモ。

ループ作成にはFXCのスイッチを利用しました。ループ検知するけど遮断しないことが出来るスイッチです。

ループさせると赤く点滅してわかりやすいです(終売品ですが)

2530 - FXC =コ

という形で FXCの1番ポートを8番ポートに接続してループを作り、2番ポートを2530側に伸ばしています。

まず、普通に接続して2530からlldpだのを吐かせて一旦ループを作ります。

ループが出来たら2530との接続は切断してしまいます、。

この状態でしばらく待つと、FXCスイッチでループ状態がエージングされます。

その後

loop-protect 1
loop-protect transmit-interval 1

と 2530側でループ検知設定をして あらためて、2530とFXCスイッチを接続すると、1秒くらいでポートがシャットダウンされます。

めでたしめでたし。

次は ブロードキャストストーム

fault-finder broadcast-storm Port-List action [ warn | warn-and-disable ] < Seconds > [ pps Number | percent Number ]

こんなコマンドですが ブロードキャストストームを検知したときにログだけにするか、ポートをシャットダウンするかが選べます(warn | warn-and-siable)

また、検知の方法として pps と percentで選べます。

特に理由はありませんが ppsのほうが好きです。 設定する数値については、通常時、どのくらいブロードキャストパケットが飛んでくるか?というところで考えましょう。

fault-finder broadcast-storm 1 action warn-and-disable  0 pps 10000

こんな具合に設定し、

あらためて、2530とFXCスイッチを接続すると、数秒でポートがシャットダウンされます。

めでたしめでたし。

ところで、ブロードキャストストームが発生している状態でloop-protectをオンにして接続したところ、 ポートをシャットダウンするまでに800MBくらいのデータが流れてきました。

こんなもんですかね?

FreeRadiusとlogとtimestamp

FreeRadius のログをファイルに保存するようにしていると、ログに追加されるtimestamp が ctime の形式になっていて、変更ができません。

手元で試していたのはCentOS6系だったので FreeRadius2.xなのですが、確認したところ、3.x, 4.x ともに変化は無いようでした。

freeradius-server/log.c at v2.x.x · FreeRADIUS/freeradius-server · GitHub

freeradius-server/log.c at v3.0.x · FreeRADIUS/freeradius-server · GitHub

freeradius-server/log.c at v4.0.x · FreeRADIUS/freeradius-server · GitHub

Users - Add timestamp with milliseconds in Radius Log

そもそもなんでこんなことを気にしたのかというと、

Elasticsearch にログを入れたい。 できれば syslogを経由したくない。

ということで、 FileBeat でElasticsearchに入れようと思いました。

この場合、FileBeatがログファイルを定期的に見に行って、ログが追加されていればそれをElasticsearchに送信するという仕組みです。

そのため、ログが書かれた時間ではなくFileBeatがログをElasticsearchに投げた時間が@timestampとして記録されてしまいます。

たまたま接続が不安定で再送した時など、再送した時間が@timestampになってしまって、若干扱いにくいところがあります。

ではどうするか、というところで、Elasticsearchにpipelineというプロセッサがあることを教えてもらえました。

Logstashなどがやっているようなフォーマット変換などをElasticearchで簡易にやれるものです。これを使ってtimestamp変換をかけてみたのですが、フォーマットに関してろくに調べなかったのでハマったというお話です。

ctime では

Thu May 24 02:19:49 2018

というような形式なのですが、Hourが02という形式になっているので、日も01とかになるか?と思っていたら

Thu May  4 02:19:49 2018

というように、日はスペースで埋められます。 そのため時間の形式として

"formats":["MMM d HH:mm:ss yyyy","MMM  d HH:mm:ss yyyy"]

と2タイプ用意しておく必要がありました。

ctimeをパースするときは気をつけましょう。

ちなみに、 syslogを経由すると syslog側でtimestampの形式を柔軟に出来るので、こんな手間はいりません。

Apache と NameVirtualHost と HTTPS

Apache には NameVirtualHost という、HTTP Header の Hostの値によって、 返すコンテンツを変えることができる機能があります。

使い方は例えば

<VirtualHost *:80>
ServerName  test1.localhost:80
DocumentRoot /var/www/test1/
</VirtualHost>

<VirtualHost *:80>
ServerName  test2.localhost:80
DocumentRoot /var/www/test2/
</VirtualHost>

こんな風に。

HTTPS対応したいときは

<VirtualHost *:443>
ServerName  test1.localhost:443
SSLCertificateFile /etc/httpd/conf/server1.crt
SSLCertificateKeyFile /etc/httpd/conf/server1.key
DocumentRoot /var/www/test1/
</VirtualHost>

<VirtualHost *:443>
ServerName  test2.localhost:443
SSLCertificateFile /etc/httpd/conf/server2.crt
SSLCertificateKeyFile /etc/httpd/conf/server2.key
DocumentRoot /var/www/test2/
</VirtualHost>

こう。

コンテンツを試しに

cat /var/www/test1/index.html
test1
cat /var/www/test2/index.html
test2

おいてみます。

早速curl と opensslでアクセスしてみましょう。

> curl http://127.0.0.1/
test1

> curl http://127.0.0.1/ -H"Host: test1.localhost"
test1

> curl http://127.0.0.1/ -H"Host: test2.localhost"
test2
> curl http://test1.localhost/
test1

> curl http://test1.localhost/ -H"Host: test1.localhost"
test1

> curl http://test1.localhost/ -H"Host: test2.localhost"
test2
> curl http://test2.localhost/
test2

> curl http://test2.localhost/ -H"Host: test1.localhost"
test1

> curl http://test2.localhost/ -H"Host: test2.localhost"
test2
  • Host に応じてコンテンツが返ってきます。
  • Host が一致しないと、最初に見つかったVirtualHostのコンテンツが返ってきます。

curl はHostヘッダを追加しないと、URLのホスト名をHostヘッダに入れます。

> openssl s_client -connect test1.localhost:443 
<test1のCertification>
GET / HTTP/1.1

HTTP/1.1 400 Bad Request

> openssl s_client -connect test2.localhost:443 
<test1のCertification>
GET / HTTP/1.1

HTTP/1.1 400 Bad Request
> openssl s_client -connect 127.0.0.1:443 
<test1のCertification>
GET / HTTP/1.1

HTTP/1.1 400 Bad Request

> openssl s_client -connect 127.0.0.1:443 
<test1のCertification>
GET / HTTP/1.1
Host: test1.localhost

HTTP/1.1 200 OK
test1

> openssl s_client -connect 127.0.0.1:443 
<test1のCertification>
GET / HTTP/1.1
Host: test2.localhost

HTTP/1.1 200 OK
test2
> openssl s_client -connect 127.0.0.1:443 -servername test1.localhost
<test1のCertification>
GET / HTTP/1.1

HTTP/1.1 400 Bad Request

> openssl s_client -connect 127.0.0.1:443 -servername test1.localhost
<test1のCertification>
GET / HTTP/1.1
Host: test1.localhost

HTTP/1.1 200 OK
test1

> openssl s_client -connect 127.0.0.1:443 -servername test1.localhost
<test1のCertification>
GET / HTTP/1.1
Host: test2.localhost

HTTP/1.1 400 Bad Request
> openssl s_client -connect 127.0.0.1:443 -servername test2.localhost
<test2のCertification>
GET / HTTP/1.1

HTTP/1.1 400 Bad Request

> openssl s_client -connect 127.0.0.1:443 -servername test2.localhost
<test2のCertification>
GET / HTTP/1.1
Host: test1.localhost

HTTP/1.1 400 Bad Request

> openssl s_client -connect 127.0.0.1:443 -servername test2.localhost
<test2のCertification>
GET / HTTP/1.1
Host: test2.localhost

HTTP/1.1 200 OK
test2
  • servername を与えないと、最初に見つかったtset1.localhostの証明書を渡されますが、 Host ヘッダに応じて、帰ってくるコンテンツが変わります。
  • servername を与えると、Hostヘッダが一致しないとBad Requestが返ってきます。
  • そもそもHostヘッダがないとBad Requestが帰ってきます。

注 openssl はconnect でホスト名を指定しても servernameには使いません。