読者です 読者をやめる 読者になる 読者になる

ぎじゅつめも

とある工学系学生が学んだことをメモするだけのブログです。

SlideshareからスライドをDL/画像DL【wget,python】

Slideshareのスライドをオフラインでも手元で確認したいことがあったので、手元にPDFとして保存できる手順をまとめました。(DLボタンが無い場合のDL方法です)

手順1.画像のクローリング

Slideshare上のスライド画像ファイルを、クローラを使ってDLします。ここでは、クローラとしてwget、言語としてPythonを用いることにします。

以下のコードを実行すれば画像を取得できます。

#!/usr/bin/env python
#coding:utf-8
import os
for x in range(ページ数-1):
    cmd = "wget https://image.slidesharecdn.com/該当パス" + str(x+1) + "固定番号.jpg"
    os.system(cmd)

具体例

例えば、
ChordアルゴリズムによるDHT入門からスライド画像ファイルをDLする場合は以下のようにします。

#!/usr/bin/env python
#coding:utf-8
import os
for x in range(335):
    cmd = "wget https://image.slidesharecdn.com/20110219chord004pict-110219072300-phpapp02/95/chorddht-" + str(x+1) + "-728.jpg"
    os.system(cmd)

実行時は、sudoなりをつけてwgetが通るようにしておきます。

手順2.DLした画像ファイルをPDFとして統合

ImageMagickを使って複数の画像をPDFへ変換します。
※参考サイト様:*1

以下のコマンドを実行すればOKです。

sudo convert 'ls -v' *.jpg 出力ファイル名.pdf

最後に(補足)

同様の手順(クロール技術)を応用すれば、Slideshare以外のサイトからファイルを取得してまとめることもできます。
ただし、時間当たりのクローリング回数が多いと対象サーバに思った以上の負荷を与えかねないので注意したいところです。

SSH設定

SSHを使えるように設定しました。
ただ、よく攻撃対象になる22番ポートの使用を避け、公開鍵認証でのアクセス設定を行いました。

SSH設定

使用ポートの変更

botのスキャン活動や不正アクセスの際、よくデフォルトのsshポート(port 22)への攻撃が行われます。そのため、今回扱うサーバではssh待ち受けポートを22以外へ変更しました。

やり方は非常に簡単です。

  1. /etc/ssh/sshd_configのPortの項目を22から待ち受けたいポート番号へ変更
  2. service sshd restartで変更適用と再起動
  3. 新たに設定したsshポートを通す様にiptables変更

公開鍵認証を設定

ユーザ名、パスワードのみでの認証だと、総当たり攻撃で突破されるリスクが高いので、公開鍵認証を採用します。

自分はサーバとしてLinux、クライアントとしてWindowsを使っています。

また、sshクライアントとしてWindows上でTera Termを使っています。Tera Termには鍵生成の機能と、公開鍵をSCP(Secure Copy:SSHを使ってファイル転送を行う機能)を使って配布する機能も持ち合わせているので簡単に認証の準備ができます。

今回はこちらのサイト様*1を参考に行いました。

こちらに書いてある通りにやれば問題ないです(解説丸投げ)。ちなみに、パスワード認証では認証先のログインパスワードなどを用いましたが、公開鍵認証時は鍵以外にも生成時に設定したパスフレーズを用います。

 

※公開鍵認証の簡単な説明

秘密鍵ファイルはid_rsa、公開鍵ファイルはid_rsa.pubとなります。秘密鍵はクライアントが使い、公開鍵はサーバが使うことになります。秘密鍵と公開鍵は暗号化と復号化のための対になっており、秘密鍵を使って暗号化したファイルは公開鍵を使ってしか復号化できません。従って、サーバ側は受け取った暗号を復号化できれば、相手がちゃんと秘密鍵を持った相手だと判別できるわけです。

公開鍵認証以外の認証を無効化

このままだと、公開鍵認証だけでなくパスワード認証もまだ使えます。

なのでパスワード認証を無効化します。

  1. /etc/ssh/sshd_configを開きます
  2. PasswordAuthentication yesをPasswordAuthentication noへ変更
  3. service sshd restartで変更適用と再起動

さいごに

これで比較的安全にSSH接続できると思います。ただ、秘密鍵の取扱いには気をつけたいですね。

 

ポート開放プロセスの特定/不要ポートの閉鎖

firewallでフィルタリングしていても、開放ポートが悪用される可能性も0ではないので、利用しないポートはなるべく閉じたいものです。

そこで今回は開いているポートを調べて、それがどのプロセスによって開放されているのか、そして不要であれば閉じるという過程を記して置こうと思います。

開放ポートの調査

netstat -antuで開放しているポートを調べます(t,uはtcp,udpに絞るオプションです)。中でも、意図的に開放した覚えのないポートを以下に表示します。

f:id:white-hawk:20170422215552p:plain

このうち、68はDHCPクライアント用なのでいいとして、他のポートは何故使われているのか調べることにします(何やら多いですね…)。

ポート開放プロセスの特定

root権限でlsofコマンドを使います。(root権限でないとうまく取得できません)

※lsofコマンドについて:manに書かれていることを簡単に説明します。lsof(list open files)はプロセスによって開かれているファイルの情報をリスト表示するコマンドです。-i オプションを使うことで、引数に指定したネットワークアドレスやポートで待ち受けているファイル/プロセスをリスト表示することができます。COMMANDはプロセスに関連付けられているコマンド名をあらわしています(デフォルトだと上限9文字)。PIDはプロセスIDで、FDはファイル記述子(read,writeなどで指定することで情報を読み書きできる番号)です。

各ポートを使っているプロセスを実際に表示させてみた結果は以下のとおりです。

f:id:white-hawk:20170422222338p:plain

f:id:white-hawk:20170422222424p:plain

rpcbind,rpc.statd,cupsd,mysqldの4つがヒットしました。

対処(閉鎖)

mysqldについて

まずmysqldについてですが、現在のところリモートから接続する機会はないので閉じておきます。閉じ方は検索するとすぐでてきます。今回参考にしたサイト様はこちら*1です。/etc/my.cnfファイルの[mysqld]配下に

f:id:white-hawk:20170422223910p:plain

を追加して、service mysqld restartで完了です。

外部からのmysqlへの接続を遮断しつつ自分だけ遠隔から利用したい場合、mysqldで3306待ち受けを行いFWでポート3306宛は落とす設定にしておいてSSHポートフォワーディングでつなぐのが良いんですかね。この辺も後でちゃんと理解しないといけませんね。

cupsdについて

CUPSはUNIX系OSで印刷を行うためのサービスのようです。このノードからの印刷は行わないのでこれも閉じます。このためにはサービスを停止して、マシン起動の度に自動で立ち上がらないようにしておく必要があります。今回参考にしたのはこちら*2

  1. サービスを特定

    f:id:white-hawk:20170422225948p:plain

  2. サービスを停止

    f:id:white-hawk:20170422230557p:plain

  3. 再起動時の起動を停止

    f:id:white-hawk:20170422230608p:plain

rpcbind,rpc.statdについて

ちなみにこれらのrpc絡みのプロセスはNFSのためのもののようです。スクショは張りませんが起動サービスとして、netfs,nfs,nfslock,rpcbind,ypbindが出てきました。NFSサーバとして利用しないので、これらを上記と同様に停止させ再起動時に起動しないようにしました。

結果

最後にnetstat -antuの結果を示します。

f:id:white-hawk:20170422232430p:plain

かなりすっきりしました。

※CLOSE_WAITになっているのは前の記事で書いたgnomeのものです。

ApacheのIPv6/IPv4の射影仕様について

Apacheを立ち上げて、待ち受けの様子をnetstatで見たところ、IPv6アドレスしか表示されていませんでした。しかしながら、外部からIPv4アドレスを指定してもちゃんとアクセスできたので、どういう仕様になっているのかを調べてみました。

状態確認

netstat -an | grep tcpの結果は以下のとおりです。

f:id:white-hawk:20170422010656p:plain

IPP(631)とssh(22)、SMTP(25)についてはIPv4,IPv6それぞれのアドレスで待ち受けています。しかしながら、Apacheが待ち受けているはずのHTTP(80)に関してはIPv6アドレスしか表示されていません。IPv4も考慮して設定したのにもかかわらずなぜ表示されていないのでしょうか?

これを調査しました。

※ちなみに0.0.0.0,::はそれぞれIPv4,IPv6において自分自身を表すネットワークアドレスで、任意の自身のアドレスで待ち受けていることを表します。127.0.0.1,::1はローカルループバックアドレスで、自分自身から自身のサービスを利用する際に指定するアドレスです。

調査

各ノードのアドレスは以下です。

・クライアントのIPv4アドレス:192.168.11.3

・WebサーバのIPv4アドレス:192.168.11.6

アイアントからこのWebサーバにIPv4でブラウザアクセスしたところ、netstatに以下のような状態が追加されました。

f:id:white-hawk:20170422012013p:plain

今回はコネクションを3つ張ってコンテンツを得ており、それぞれIPv4アドレスを指定してもコネクションを張れていることがわかります。ブラウザでも実際のコテンテンツを取得で来ました。

ただし、netstatでのコネクションの実際のアドレスを見てみると、いわゆるIPv4-mapped IPv6アドレス/IPv4射影IPv6アドレスと呼ばれるアドレスに変換されていることがわかります。つまり、IPv4アドレスでアクセスしてもWebサーバ側のソケットではIPv6アドレスとして処理されています。IPv4射影アドレスとは、一般的に先頭80bitが0、続く16bitが1、残りがIPv4アドレスであるIPv6アドレスです。これはIPv6ノードが、IPv6をサポートしていないIPv4ノードと通信をおこなうための仕組みです。

 

Webサーバ内部での処理はIPv6アドレスで行われていたわけですが、実際にリンクへ流すパケットでは双方がIPv4アドレスを使っていました。

f:id:white-hawk:20170422022219p:plain

結論・考察など

射影アドレスを使っていることから、恐らくApacheIPv6ソケットで通信を待ち受けており、IPv6に対応していないノードからIPv4でアクセスされても処理できるように射影アドレスに変換してサーバ内ではIPv6アドレスとして処理を行うようになっているようです。

つまり、netstatなどの見掛け上はIPv6でしか待ち受けていないように見えてもちゃんと内部的にはIPv4でも処理しているみたいです。(射影がnetstatの結果にどのような形で反映されているのかがなんとなく掴めました)

関連サイト

後日同様のことを調べてらっしゃるサイト様を探したところ、以下のQiita記事が見つかりました。

qiita.com大体疑問点は同じなのですが、ちゃんとnetstatのコードを読んでいらっしゃって、射影アドレスが反映されるフラグがIPV6_V6ONLYにあることまで突き止めていらっしゃい ました。記事によるとこのフラグが真だとIPv6IPv4が分けられるようで、上記のsshやIPPはこれに当たるようです。逆に偽だと今回のように射影されて透過 的に処理できるようになるとのことでした。

 

また、海外でも同様の疑問をお持ちの方がいらっしゃったようです。

askubuntu.com今回の仕様はIPv6-IPv4フォールバック(IPv6でアクセスできなかったらIPv4でアクセスする)機構の特徴があること、それから、IPv4ノードとIPv6ノードでも互いに通信できるような互換のためにありなおかつそれぞれのソケットをもつ問題を解消するためにあると解説されていました。

身に覚えのない通信先とCDNについてのめも

前置き

netstatで各ポートの様子やコネクションの状態を確認していたら、見知らぬアドレスに対するハーフクローズの通信を見つけました。ずっとハーフクローズだしなんぞこれ。。。マルウェアの類だったら嫌だなぁ。。。ということでちょっと調べてみたのでメモしておきます。

また、間違っている認識や記述があれば指摘していただけると幸いです。

状態

80番ポートを使った通信をnetstatで確認したら下記のような表示になりました。

f:id:white-hawk:20170417191945p:plain

内部ホストから外部の110.232.152.33に対してCLOSE_WAITの状態を保っていました。CLOSE_WAITは、TCPの状態遷移図における状態の1つです。このホストがコネクションクローズのためのFINを受け取りACKを送ったものの、その後のFINを送信できていない状態で、これをハーフクローズと呼びます。ハーフクローズの状態があまりにも長く続いているので不審に思いました。

そして110.232.152.33とはどこぞやということで名前解決してみた結果…

f:id:white-hawk:20170417193044p:plain

回答から、deploy.akamaitechnologies.com配下のノードであることがわかりました。

通信相手についての調査結果

akamaitechnologies.comということはあのCDNを展開しているAkamaiさん…?Akamaiさんのドメインでよく知っているのはakamai.comだけど、コンテンツ配信用のドメインはそういえばなんなんだろうなぁ…などと思いつつ調べてみると、国内外問わずいろんな質問サイトに同様の質問がありました。この回答によると通信相手はやっぱりAkamaiさんのコンテンツ配信に関わるノードのようです。今回これを観測したホストはブラウジングなどクライアントとして用いていたので、その際利用したものと思われます。

AkamaiのCDNの仕組みは、オリジナルサーバを管理しているADNSのCNAMEにAkamaiのエッジサーバのドメインを登録することで、クライアントがエッジサーバ(オリジナルサーバの内容をキャッシュしたサーバ)からコンテンツを取得するようになるというものです。エッジサーバは、自身に適切なキャッシュがなければリバースプロキシとして機能し、リクエストをオリジナルサーバへ送ってキャッシュを得ます。

今回の110.232.152.33はCDNのエッジサーバってことで良いんでしょうか…?ポートスキャンをかけてみると80以外にも443が開いていました。

また、110.232.152.33についてwhoisで調べてみると以下のことがわかりました。

f:id:white-hawk:20170417204805p:plain

どうやら今回はSo-netのASにAkamaiのエッジサーバがあるっぽいですかね。実際にAS2527(So-net Entertainment Corporation)からAkamaiコンテンツが吐かれているというソースもありました*1。ここ*2でも確認しました。あれ、でもそういえばSo-netって自社でCDN持ってるんじゃなかったっけ、違ったっけ…と思いつつ調べていくと、一応、自社CDNとAkamai CDNなどによるマルチCDNといった構成を取る事業者さんもいるらしいです。その辺りも上記のJANOGにおける解説がわかりやすいです。

蛇足ですが、今まではほとんどのバックボーントラヒックはTier1を介していたのですが、それが近年では、Tier1までいかずHyperGiant(Google,Akamai)やCDNを構成するISPを介すようになった件なども上記注釈リンクにて説明されていています。トランジットへ通行料を払うよりCDNを介する方がコストも安上がりで応答性も上がったので仕方ないですね。

コネクションについて

ハーフクローズ状態がずっと続いているのが気になります。ハーフコネクションは、コネクション確立中に片方のホストが落ちた場合などに発生します。今回は、こちら側がFINを受け取った後ACKを送信してダウンしたのかな…と思ったのですが何やらホストが元気でもCLOSE_WAITとなっている模様。もしかしたらAkamaiのエッジサーバの仕様が関わっているんでしょうか?状態が維持されたままなのはkeepaliveが変に働いているせいかとも思ったのですがwiresharkでパケットをキャプチャし続けた結果keepaliveは確認できませんでした(KeepAliveが有効なものの、KeepAliveパケット送信前に何らかの理由で接続が切れている…?)。

AWSのElastic Load Balancing(ELS)では、HTTP KeepAlive時間をLBのアイドルタイムアウト時間よりも大きい値にしなければ、LBのインスタンスへの接続を確実に閉じられない=ハーフクローズなどが生じる可能性があります。このような形で、通信先のいずれかのノードにコネクションを正常に閉じられない問題があるのかもしれません。

ちなみに110.232.152.33とはOS起動後すぐにコネクションを確立し、さらに一定時間おきにCLOSE_WAIT,LAST_ACKでコネクションを閉じ、また3wayハンドシェイクを経てESTABLISHEDへ移行するといった状態遷移を繰り替えしている模様。

通信を行っているプロセス(原因)

継続的にパケットをキャプチャしていると以下のようなHTTP GETリクエストを投げていました(というか110.232.152.33宛のリクエストで確認できたのがこれだけでした)。

0.013133732 192.168.11.6 -> 110.232.152.33 HTTP 378 GET /cgi-bin/mgetmetar.pl?cccc=KBOS HTTP/1.1

恐らくgnomeの天気概況機能のためのリクエストだと思われるので、不審(マルウェアの類)ではないですが、gnome-pannelもAkamaiのサーバを利用しているんだなぁと… つまり、ブラウザ立ち上げなくてもAkamaiエッジサーバに定期的にコネクションを張っていたのはこいつのせいだったみたいです。OS起動後すぐにコネクション張っていたのも納得ですね。

まとめ

・見覚えの無い宛先IPアドレスAkamaiのエッジサーバだった

・今回のAkamaiエッジサーバはSo-netISP)に設置されたもの

gnome-pannelがエッジサーバに対してリクエストをなげていた

・恐らくAkamaiを利用する過程のいずれかのノードでハーフクローズの原因がある

大体通信先の謎等は解決しましたが、勝手にコネクション張ってハーフクローズで放置するアプリケーションは考えものですね…

FW (iptables) の設定

固定IPアドレスを割り当ててサーバを外部へ公開する前に、サーバのFW(Firewall)の見直しを行います。間違っていたら指摘していただけると幸いです、

FWの設定

iptablesについて

ここで扱う純粋なFWは、トランスポート層以下のヘッダ内容を見てパケットの処理を決めるものです。LinuxではFWのプログラムとしてIPv4用にiptablesIPv6用にip6tablesが提供されており、今回はiptablesを利用します。設定ファイルは/etc/sysconfig/iptablesになります。

iptablesでは、パケットの処理の規則をルールと呼び、処理内容(受け入れ、遮断など)をtargetと呼びます。このルールを列挙したものをチェインと呼び、このチェインをまとめたものをテーブルと呼びます。デフォルトで用意されているテーブルにはフィルタ目的のfilterやIPマスカレードのためのnatなどがあります。パケットがFWに到達したら、まず適用するテーブルを選択し、その中で該当するチェインを選択し、その中の該当するルールに沿って処理を実行します。

パケットフィルタリングで標準的に使われるのはfilterテーブルですので、今回もfileterテーブルのチェインとルールを操作して、遮断するパケットと通過させるパケットを制御していきたいと思います。filterテーブルには、流入パケットを扱うINPUTチェイン、転送パケットを扱うFORWARDチェイン、流出パケットを扱うOUTPUTチェインがあります。また、それぞれのチェインには、ルールに該当しないパケットへの処理方針を表すPolicyというものがあります。

また、ルール設定を行う上で*1様が凄くわかりやすいのでおすすめです。

設定方針

ルールに欠陥があり不用意にパケットを受け入れてしまうことを懸念してINPUTのPolicyをDROPとします。また中継器として機能させる予定はないのでFORWARDのPolicyもDROPとしています。OUTPUTのPolicyのみACCEPTとしています。また、INPUTでスキャン活動や攻撃と思われるパケットを落とします。

設定内容

設定変更後、service iptables restartで適用できます。設定したiptablesの内容を以下に記述します。


# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
###############################################################
#ローカルホストI/F宛は通過

-A INPUT -i lo -j ACCEPT

###############################################################
#コネクション確立済みのパケットは通す

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

###############################################################
#Ping flood対策(icmp echo requestをhashlimitにより受信制限)
#ICMP echo requestは毎秒1個に制限

-A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

#log
-A INPUT -p icmp --icmp-type echo-request -j LOG --log-prefix "ping_flood:"
-A INPUT -p icmp --icmp-type echo-request -j DROP

##############################################################
#HTTP Flood(F5)対策(HTTPパケットをhashlimitで制限)
#送信元IPアドレスごとにパケットカウント
#個数が50を越えると10/sの制限をかける,期間は120000ms

-A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -m hashlimit --hashlimit-name t_http_flood --hashlimit 10/s --hashlimit-burst 50  --hashlimit-mode srcip --hashlimit-htable-expire 120000 -j ACCEPT

#log
-A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -j LOG --log-prefix "ping_flood:"
-A INPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -j DROP

###############################################################
#SYN flood対策(SYNパケットをlimitにより受信制限)
#SYNパケットが1個到着したらすぐに制限(ほぼ常に制限状態)
#制限状態では、サーバ宛のSYNパケットを毎秒50個へ制限

-A INPUT -p tcp -m multiport --dports 80,443 --syn -m limit --limit 50/s --limit-burst 1 -j ACCEPT

#80,443以外のSYNはSSHを許可
#SSHログインを総当たり攻撃で突破することを先延ばしする
#300秒間に5回までのアクセス制限

-A INPUT -p tcp --syn --dport 22 -m recent --name sshattack --set
-A INPUT -p tcp --syn --dport 22 -m recent --name sshattack --rcheck --seconds 300 --hitcount 5 -j LOG --log-prefix "ssh_bruteforce:"
-A INPUT -p tcp --syn --dport 22 -m recent --name sshattack --rcheck --seconds 300 --hitcount 5 -j DROP
-A INPUT -p tcp --dport 22 -m tcp -j ACCEPT

#log
-A INPUT -p tcp --syn -j LOG --log-prefix "syn_flood:"
-A INPUT -p tcp --syn -j DROP ############################################################## #ステルススキャン対策 #3wayハンドシェイクを完遂しない、コネクションの足がつかないスキャン #nmapでありがちなスキャンパケットはとりあえず落としてログをとる #該当ルールが多すぎるのでSTEALTH_SCANチェインを作成 -N STEALTH_SCAN -A STEALTH_SCAN -j LOG --log-prefix "stealth_scan: " -A STEALTH_SCAN -j DROP #ステルススキャンと思われるパケットは全てステルススキャンチェインへ -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags ALL NONE -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags ACK,PSH PSH -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags ACK,URG URG -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j STEALTH_SCAN -A INPUT -p tcp --tcp-flags FIN,URG,PSH FIN,URG,PSH -j STEALTH_SCAN
-A INPUT -p tcp --tcp-flags ALL FIN -j STEALTH_SCAN
-A INPUT -p tcp --tcp-flags ALL ACK -j STEALTH_SCAN
-A INPUT -p tcp --tcp-flags ALL FIN,ACK -j STEALTH_SCAN ######################################################### #DNS用 -A INPUT -p udp --sport 53 -j ACCEPT -A INPUT -p tcp --sport 53 -j ACCEPT COMMIT

 

 

ステルススキャン時のフラグの組み合わせを網羅するのは骨が折れるので、一部*2様のやり方を流用させていただきました(いろいろな攻撃や偵察を考慮していらっしゃるのでとても参考になりました)。

ステルススキャンは、1番目がNULLスキャン、2番目と3番目と7番目、8番目は名称はわからないものの正規の手順ではありえない組み合わせによる挙動 を見るスキャン、4番目はFINスキャン、5番目と6番目も名称不明ですがコネクション確立前には送られないはずのフラグが立ったパケットによるスキャン かと思われます。9番目以降は独自に追加したルールで、それぞれ、クリスマスツリースキャン、FINスキャン、ACKスキャン、Maimonスキャンを検知するルールです。もっと様々なスキャン方法を網羅したい場合nmapのスキャンテクニック*3などを参考にすると良さそうです。

HTTP Floodは送信元IPアドレスをスプーフィングできないのでhashlimitで送信元を取り、制限をかけるようにしています。これによって攻撃者は制限され正規ユーザは制限を受けません。

ホストのリソースを食いつぶすSYN Flood対策ですが、スプーフィング可能な攻撃なのでhashlimitを使って送信元IPアドレス単位での制限は有用ではないんじゃないかなぁと考え、limitを用いています。これらhashlimitやlimitの制限パラメータは環境に合わせた改善の余地がありそうなので適宜チューニングしていこうと思います。また、万全を期して別途SYN Cookie法も有効にする予定です。

同様にICMP Floodも容易に送信元IPアドレスを詐称できるのでlimitで制限をかけました。hashlimitをかけている方をたまに見かけますが、もしかしたらスプーフィングしていない純粋なpingを用いたfloodのみを対象にしているのかなぁと(pingコマンドは送信元IPアドレスを指定できますが、確か未割り当てのアドレスを指定すると送ってくれないので…)。

ICMP Smurf攻撃ネットワーク管理者がルータでブロードキャストアドレス宛のリクエストパケットを破棄するなどの対策を行っていれば防げるので今回はiptablesに対策を記述していません。もし記述するならicmp echo replyの流入を制限したり、踏み台となるのを防ぐためにicmp echo replyの流出を制限するルールを記述すればよいと思います。

DNS amp対策の一貫として、dnsパケットの受信制限を追加するのもよいかもしれません。

もっとも、ここまでで登場した中で帯域型攻撃として働くものはエンドホストで落としてもエンドホストに至るまでのリンク/中継器に影響が出ているので根本的な解決にはなりません。しかしやらないよりはマシなので実装しています。

sshポートへの総当たり攻撃を回避するためにsshポートへも接続回数制限を設ける方が良いと思ったのでこれもhashlimitで設定しようと思ったのですが、*4様の手法の方が明解だったのでこちらを参考に記述しました。

ログについて

dmesgコマンドで取り急ぎメッセージログを見ることはできますが、rsyslogの設定を変更しないと/var/log/下にログファイルは生成されません。そこで*5様の記述に沿ってログの設定を行いました。

すなわち、/etc/rsyslog.confのRULES配下に

kern.info /var/log/iptables.log

を追記。設定変更後は/etc/init.d/rsyslog restartで変更適用。これでログを吐かせるようにしました。

また、ログの肥大化を防ぐためにログのローテーションも行おうと思います。まだ実行しておらず後で行う予定です。

実際のログ

閉じたローカルネットワーク環境で実際にSYN Floodを観測させました。この場合、/var/log/iptables.logに以下のようなログが大量に残ります。192.168.11.5はサーバのローカルIPアドレスです。

f:id:white-hawk:20170322020910p:plain

ただ、今回のこのログ、実は他ホストからTCPポートスキャン(SYNスキャン)をかけたものです。SYNスキャンはステルススキャンの中でも最もポートスキャンとして検知するのが難しいので今回はsyn_floodでログを出すようにしています。

また、スキャン実行を行うとともにiptables.logをtail -fコマンドでリアルタイム監視していたのですが、RTTを考慮してもログが出力されるまで4,5秒ほどレイテンシがありました。

ping floodも以下のようにちゃんとログを吐いてくれました。

f:id:white-hawk:20170322072713p:plain

ping floodは以下のようにシェルスクリプトを記述して実行しました。※悪用厳禁。

#!/bin/sh
COUNT=0
while [ $COUNT -lt 1000]
do
 ping 192.168.11.5 -n 1000 -s 1400 > /dev/null &
 COUNT=$(( $COUNT+1 ))
done

nmapを用いてFINスキャンを行った場合のログは以下のようになりました。

f:id:white-hawk:20170322225926p:plain

ログメッセージがstealth_scanだけでも、ログからフラグまで見えるのでどんなスキャンかが判別できますね。

sshポートについて

botのスキャン活動などではsshポートはよく標的になるので、他のポートへ変更するのが無難のようです。これも今後の予定です。

Ciscoルータ設定作業めも

Ciscoルータをもつ友人宅で勉強会を行ってきました。Ciscoルータへ直接設定を行うのは某インターンで経験したりしていたのですが、結構忘れていたので復習の意味を込めてめもを残しておきます。

作業環境

用意した製品・道具類

Ciscoルータ 1812-J

・LANケーブル

・コンソールケーブル(D-Sub)

・D-Sub⇔USBシリアル変換ケーブル

・エンドホスト用ノートPC2台

・コンソール用ノートPC1台(Windows、Tera Termインストール済み)

Ciscoルータ 1812-Jについて

仕様書上、このルータは以下のポートを持っていました。

・WANポート(fa0,fa1)

・LANスイッチポート(fa2~fa9)

ここで、faはFast Ethernetの略称です。

L3スイッチ(及びL3スイッチ内臓ルータ)の構成は以下のように考えています。図ではVLANを分けて描きましたが、今回は全てのLANスイッチポートがVLAN1に属しています。SVIはVLAN(内部スイッチ)と内部ルータのインタフェースです。Ciscoの説明にあったWANポートが所謂ルーテッドポート、LANスイッチポートが所謂スイッチポートに当たる物と捉えています。また、今回はVLANの設定は省略して次回にまわそうと考えているので、スイッチポートは使用せず、エンドホスト側も、直接ポートにIPアドレスを振れるルーテッドポートを使用しました(詳細はネットワーク構成へ)。

f:id:white-hawk:20170319054358p:plain

ネットワーク構成

ルーティングを確認するため、最低限のネットワークとして以下のようなトポロジを考えました。エンドホストはそれぞれE1,E2であり、ルータはそれぞれR1,R2です。上述したように、便宜上今回はLAN側もルーテッドポートを使用しています(図中の※印インタフェース)。 

f:id:white-hawk:20170319061034p:plain

作業内容

基本的なコマンドや仕様の把握と、静的ルート設定、簡単な動的ルート設定を行いました。

ルータ設定のための接続

Cisco機器への接続方法は主にコンソール接続、VTY接続があります。以下のにその手法を記述します。物理的な接続を行った後はTera Term等を用いてIOSへアクセスします。

コンソール接続

ルータの初期設定がすむまではコンソール接続しかできません。従って今回はコンソール接続を行います。コンソール接続では、設定したいルータのコンソールポートとPCをコンソールケーブルを介して接続します。今回コンソール用端末側にD-Subポートがなかったため、D-Sub⇔USB変換ケーブルを介して接続しました。

VTY(仮想端末)接続

初期設定が済んでから使用可能な接続方法で、ネットワークを介してtelnetsshでリモートログインして設定を行います。Cisco機器とコンソール用端末がネットワークを介して接続されていれば物理的な接続は完了です。ちなみにエンドホストからCisco機器へのtelnet接続だけでなく、Cisco機器からCisco機器へのtelnet接続も可能です。

Cisco IOSとモード切り替え

Cisco製品上では、おおよそCisco IOSというCLIベースのOSが動作しており、このソフトウェアを介して機器への設定を行います。またIOS操作時は、いくつかのモードを切り替えながら設定を行っていきます。セキュリティの観点からアクセスレベルが設けてあり、主に以下のモードがあります。※ルータ名はRouterにしています。

モード 概要
ユーザモード

接続時の最初の状態。機器の一部の情報を見ることが出来ます。 端末での表示は以下のようにホスト名を”>”で区切るようになっています。

f:id:white-hawk:20170320041621p:plain

特権モード

ユーザモードからenableコマンドで権限者のみが移行できるモード。機器の全ての情報の参照やデバッグ、ツール(pingやtracerouteなど)の実行ができます。disableコマンドでユーザモードに戻れます。 端末ではホスト名に続き"#"が続きます。

f:id:white-hawk:20170320041857p:plain

グローバルコンフィギュレーションモード

特権モードからconfigure terminalコマンドで移行できるモードです。機器全体に関わる様々な設定(機器名やパスワードの設定など)が出来ます。exitコマンドで特権モードへ戻れます。端末では以下のように表示されます。

f:id:white-hawk:20170320041937p:plain

特定コンフィギュレーションモード

グローバルコンフィギュレーションから移行できるモードです。機器の特定の箇所に設定を行うためのモードです。特定コンフィギュレーションモードは、厳密にはインタフェースコンフィギュレーションモードやルータコンフィギュレーションモードなど、特定の箇所に応じたモードが存在します。exitでグローバルコンフィギュレーションモードに戻れます。

例えばインタフェースコンフィギュレーションモード時は以下のように表示されます。

f:id:white-hawk:20170320042354p:plain

コマンドの補完と省略

 各種コマンドは、コマンドが一意に判別できる文字列まで入力し終えたら、[tab]キーで補完することができます。また、補完可能な文字列だけでそのコマンドの実行も出来ます。例えば、enableコマンドはenでも実行可能ですしconfigure terminalコマンドは、conf tでも実行可能です。

I/F(ルーテッドポート)へのIPアドレス割り当て

まず、グローバルコンフィギュレーションモードにおいて、設定を行いたいインタフェースを指定してインタフェースコンフィギュレーションモードへ移行します。移行のためのコマンドは、interface [規格] [インタフェースの番号]となります。例えば、今回の場合、R2のFast Ethernetの1番目のポートに設定を行いたいため、以下のように入力します。fastethernetはfaと省略することも可能です。

f:id:white-hawk:20170320043630p:plain

※ちなみに、インタフェース番号の表記としてn/0/nというものがあります。これはスタック可能なボックス型スイッチにおいて適用されるもので、最初の数字がスタック位置、次の番号は0固定、最後の番号がインタフェースの位置となります。

次にインタフェースにIPアドレスを割り当てます。今回は192.168.3.254/24を割り当てたいので、ip addressコマンドを用いて以下のように行いました。今回用いたip addressコマンドの形式はip address [IPアドレス] [サブネットマスク]となっています。

f:id:white-hawk:20170320044518p:plain

最後に、I/Fを有効にするために、no shutdownコマンドでたちあげます。スイッチングポートはデフォルトでupですが、ルーテッドポートはデフォルトでdownなのでたちあげます。

f:id:white-hawk:20170320044603p:plain

これでI/FへのIPアドレス割り当てと有効化が完了しました。今回は各ルータにおいて4つのI/Fに設定が必要なので同様に行いました。

ルータからのツール実行

ルータに実装されているツールを特権モードから実行できます。例えばpingをエンドホストへ向けて送ってみた結果を以下に示します。

f:id:white-hawk:20170320045054p:plain

"!"と表示されているのはecho replyが帰ってきてpingが成立したものです。ここでは5回中5回のpingに成功しています。逆にecho requestを送ったもののタイムアウト時間までにecho replyが帰ってこなければ".(ピリオド)"が表示されるようです。

※ちなみにコマンドの強制中止は[Ctrl]+[Shift]+[6]で行えるようです。

また、pingだけ打つと拡張pingとなり様々なオプションを指定できます。

f:id:white-hawk:20170320045443p:plain

tracerouteも実行可能。(1ホップしかないのでトレースの意味薄いですが実行できるという意味で掲載)

f:id:white-hawk:20170320045537p:plain

Interfaceの状態について

Interfaceの情報を表示すると、[インタフェース名] is upなど記載があります。これはInterfaceが搬送波を検出できる状態にあるか(レイヤ1接続が有効か)どうかを表しています。upの場合できる、downの場合できない、administratively downの場合設定上できなくなっていることを表します。

ラインプロトコルについて

Cisco機は定期的にキープアライブ信号のやり取りをしているようで、隣接ノードまで信号が届かなくなったり、届くようになったりするとその旨が端末上に表示されます。すなわち、論理的な接続の有効性がLine protocl is (up/down)の表記でわかるようになっています。論理的な接続が切れる原因はリンクの問題、ノードの問題に区別されます。

例えば意図的に隣接ノードの電源を落とすと下記のようなメッセージが表示されます。

f:id:white-hawk:20170320050805p:plain

再び立ち上げると下記のようなメッセージが表示され論理的な接続が回復したことがわかります。

f:id:white-hawk:20170320051028p:plain

※ちなみに

隣接ノードのMac bookをスリープモードにすると以下のようにLine protocolのdownとupが瞬時に表示されました。以下がその様子です。

f:id:white-hawk:20170320051546p:plain

これはスリープ中も通信ができるようにするために論理的な接続を有効にしているようで、恐らくMacのPower Nap機能によるものかと推測しました。ちなみにpingは通りませんでしたので、一部の通信のみ有効なのでしょうか...。

ホスト名の変更

今までルータにデフォルト名(Router)を用いていましたが、2台あってややこしいのでホスト名を変更します。ホスト名変更はグローバルコンフィギュレーションモードでhostname [ホスト名]を実行することで可能です。

f:id:white-hawk:20170320051944p:plain

各I/Fの情報表示

各I/Fに対するIPアドレスの割り当て状況や接続性をリスト表示するには例えばshow ip interface briefコマンドがあります。

f:id:white-hawk:20170320052332p:plain

BRIはISDN用のI/Fです。

DuplexやVLANなどのステータスを確認したい場合はshow interface statusで行えます。

f:id:white-hawk:20170320053200p:plain

また、各I/Fごとの詳細を見たい場合はshow interfaceで確認できます(実行結果略)。

スイッチポートへのIPアドレス割り当て

スイッチポートはルーテッドポートと異なりL2相当の役割を果たすためIPアドレスをそのまま割り当てることは出来ません。以下は割り当てを試みた場合のエラーメッセージ。

f:id:white-hawk:20170320053446p:plain

しかしスイッチポートにVLANを割り当て、VLANにIPアドレスを割り振ることで疑似的にスイッチポートがIPアドレスを持つように振る舞わせることができるはずなので、次回実際に行おうと思います。

設定した内容の保存

設定の内容は、不揮発性RAM(NVRAM)に書き込まなければ次回の起動時にも反映されません。従って設定を保存するには、copyコマンドを使ってNVRAMへ設定の書き込みを行います。

f:id:white-hawk:20170320054525p:plain

running-configはメモリ上にあり、startup-configはNVRAMにあります。copyコマンドは第一引数の内容を第二引数へコピーするものです。copy run startという省略形や、write memory、wrでも同じことが実行されるようです。

静的ルーティング

エンドホスト、ルータ共にI/Fに静的IPアドレスの割り当てを行いました。各エンド間で通信を行うためには、各ノードのルーティング設定を行う必要があります。今回はまず静的ルートを記述します。R2でグローバルコンフィギュレーションモードに入った後、静的ルートを以下のように記述します。

f:id:white-hawk:20170320054943p:plain

ip route [宛先ネットワークアドレス][宛先サブネット][隣接ノードのIPアドレス]という記述で静的ルートを追加できます。

機器のルーティングテーブルはshow ip routeコマンドで見ることが出来ます。

f:id:white-hawk:20170320055317p:plain

f:id:white-hawk:20170320055355p:plain

うまく反映されたようです。ちなみにSは静的ルート、Cは直接機器に設定してある接続を意味しています。他にもRIPで動的に割り当てられたならばR、OSPFならばOなどと記載されます。

この設定をR1にも行います。また、各エンドホストのデフォルトルートをそれぞれのルータに設定します。

その後、うまく静的ルートが働いているかを確認するためにE2からE1へpingを飛ばしてみました。

f:id:white-hawk:20170320055853p:plain

ちゃんと静的ルートでエンド間の通信ができました。traceroute実行結果も以下のように意図したものとなりました。

f:id:white-hawk:20170320055952p:plain

※ルートの消し方

動的ルーティングも試したいので、設定した静的ルートを手動で消します。

f:id:white-hawk:20170320060145p:plain

静的ルート追加時のコマンドにnoをつければ可能です。以下は実際に消えたことの確認です。

f:id:white-hawk:20170320061453p:plain

動的ルーティング(OSPF)

リンクステート型ルーティングプロトコルであるOSPFで動的にルートを生成したいと思います。R1では以下のようなコマンドを打ちました(友人がワイルドカードマスクをサブネットマスクと勘違いして入力したらしいので次回があれば修正して実験しなおしたものに画像を差し替え予定です。今回のトポロジが幸いし挙動としては変わりません)。

f:id:white-hawk:20170320060445p:plain

router ospf [process id]で適当なプロセスを走らせます(1つのルータで複数のOSPFを走らせることができますが非推奨です)。

network [ネットワーク/IPアドレス] [ワイルドカードマスク] area [エリアID]で該当するI/Fにエリアを割り当てます。OSPFではリンクステートをエリアごとに集約します。また、原則としてバックボーンエリア(area 0)が必要ですので、今回これを割り当てています。ワイルドカードマスクは、一回のnetworkコマンドで複数のI/Fにエリアを割り当てるために指定するもので、2進数で”0”の部分は合致するかどうか検証し”1”の部分は検証しないと判断されます。従って上記のように192.168.1.0も192.168.2.0もどちらもエリア0に所属させたい場合network 192.168.0.0 0.0.255.255の方が効率的かつワイルドカードマスクの観点で正確と思われます。

R2でも同様の設定を行いルーティングテーブルを見てみる。

f:id:white-hawk:20170320062614p:plain

f:id:white-hawk:20170320062711p:plain

ちゃんとOSPFによりルートが追加されています。pingでの通信疎通テストは省略。

イベントの表示

試しにOSPFによるイベントを表示してみます。debugコマンドで指定したイベントを表示することができるようになります。

f:id:white-hawk:20170320063133p:plain

OSPFのHelloパケットのやりとりが観測されました。デバッグを停止するにはno debu allコマンドをつかいます。

終わりに

今回は簡単なCiscoルータの操作を行いました。今後友人宅を訪問する際に、友人が気乗りすればまた追加で実機を操作してそのめもを残すかもしれません。