ログに残りにくい攻撃について(2019-11-21、2026-04-12:更新)
今回はSYN FloodやらIP詐称やらがメインです。
ふつうに(?)アクセスを止める話は別のメモで解説します。
各アプリ(apache、postfix、wtmpとか)でログとして残る攻撃は、
fail2banなどで監視&拒否すれば良いわけですが、
それができるのは、あくまでアプリとの通信が成立した場合だけであって
例えば、
SYN Floodとかポートスキャンとかpingのような攻撃は
ログに痕跡が残らなかったりするわけです。

図が示すのは、通信が成立する過程で、
外から通信を受ける時は下から順に登ってくる、
アプリから外へ発信する時は上から下へ降りていくイメージです。
だからpingとか(=ICMP)、SYN Floodとか(=TCPの接続前)による攻撃は
一番上のアプリ層までデータが登って来ないから、ログにも載らないのです。
SYN Floodの例†
80や443ポートめがけてひたすらSYNだけを投げてきます。
通常のTCP接続の手順は以下ですが、
TCP接続時の3Wayハンドシェイク
|<- 1.SYN ------| 1.SYNが届く
|-- 2.SYN-ACK ->| 2.受信確認のACKと、こちら側からのSYNをセットで返す
|<- 3.ACK ------| 3.こちらのSYNに対するACKが届く
| | (が、3は投げずに1.SYNを投げ続けるのがSYN Flood)
上の図で、「3.ACK」を投げずに、受け側をずっと待たせたままにするのがSyn Flood です。
- さらに、送信元IPは詐称して投げる場合があります
- その上、送信元ポートも80/443番(=http/https)とかに詐称して投げてきます
- その結果、こちらのAck応答がどこかの知らない企業のWebサーバへ送られます
- 80(http)や443(https)に限らず、TCPポートならどこでも良いので、見境なく大量に投げてきます
(telnet/ssh/http/smtpなどはポートが開いている確率が高いので狙われ易い)
はじめの部分を、それっぽい絵で説明・補足すると...
ただ、送信元を詐称するのは通常は不可能です。
(その理由は次の図)
それができるのは、攻撃元のネットワークのセキュリティがヨワヨワだったり、国や組織が用意した「攻撃用のネットワーク」だったり、誰も管理していないネットワークだったりする場合なのだと思います。

なんにせよ、
TCPセッションの1つ1つが資源を確実に消費するわけですし、
大量に来るとリソースがいっぱいになって、正規の通信も不可能になる、
というのがDoS攻撃です。
たとえばapacheなどのWebサーバでは
セッション数/プロセス数/スレッド数等の上限を設定するのですが、
ここを多めに設定したとしても、OSにも各ユーザ毎に上限はあって
("ulimit -a" コマンドでプロセス数やらメモリやらの上限が表示できます)
いずれにせよ資源には限界があります。
そんな無駄な通信はできるだけ阻止したいところですが、
そもそも、攻撃されていることに気が付かなかったり気がついたりする、
以下、そういう内容のメモです。
具体的な確認例†
ケース1:snortに載る謎のSYN-ACK†
偶然みつけたログですが。
うちのサーバでは外に向けての通信はほとんどやらないので、
ほんの遊びゴコロセキュリティ対策として外への80, 443通信をsnortで監視していたら、
たまに、よそのWebサーバ目がけてSYN-ACKを飛ばしていることが分かりました。
TCP接続時の3Wayハンドシェイク
|<- 1.SYN ------| 1.詐称IPからSYNが届く
|-- 2.SYN-ACK ->| 2.これがsnortで検出されていた
|<- 3.ACK ------|
|-(TCP connect)-|
つまり、どこかの攻撃者が送信元ポートに80番を指定して(詐称して)うちのサーバへ攻撃してきた感じです。
うちのWebサーバは本物か偽物かにかかわらず、とりあえずSYN-ACKを返した、と。
通常は送信元ポートにWell-knownポート(1023番以下)あるいは低い番号帯を使うことは無いので
攻撃者はどこかのWebサーバへの嫌がらせが目的で、偽のSYNを世界中にばらまいているのだと思います。
(Well-knownポートで相手からSYNを受けることはあっても、SYNを投げることは無いはず、たぶん)
そのため、
送信元ポートが1023以下*1から来る通信はfirewallで止めてしまうことも一考したほうが良いと思います。
そして、
これと同じ理屈がICMPにも言えます...つまり、詐称したpingをばらまいて、応答をどこかのサーバへ一斉にぶつける攻撃など。
ICMP自体は調査やら保守やらには必須なので、止めるかどうかはサーバの用途次第ですよね...
たとえばWebに繋いでいるが公開はしていない(特定少数の人しかアクセスしない)目的のサーバなら、存在自体を隠すために、あえてICMPは止めるのかもしれませんし。OSによってはデフォルトでICMP拒否していますし。
(みんなどうしているのか疑問に思ってWeb検索してみると、どうするべきとは一概には言えないことは分かりました)
ケース2:netstat に載る「大量の」SYN_RECV†
なんか、大量のSYNが飛んできて、netstat(後述)を見てびっくりしました。
IPアドレスで言えば xx.xx.xx.1、xx.xx.xx.2 (中略) xx.xx.xx.255 のように
特定のアドレス帯を連番で、あるいはランダムに詐称して攻撃してきます。
その(詐称されているっぽい)IPアドレスを "dig -x IPアドレス" で確認すると、
特定の大手企業が所有する一群だったり(=その企業を攻撃するのが目的?)、
なんの脈絡もなくただ連番だったり、様々でした。
偶然多いのではなく、明らかに攻撃である、というのは
接続数の違いを見れば分かります。
通常はTCPハンドシェイクは一瞬で終わるので、SYN_RECVのまま残る数は少ないはずです(途中で通信断とかで、ごくまれに残る程度)
netstat -tan
# t は TCP接続
# a は ぜんぶ(all)。ユーザ自身以外の接続も見る。
# n は名前変換をしない。IPアドレスやポート番号を数字のままで出す
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
(中略)
tcp 0 0 aa.bb.cc.dd:443 xxx.189.9.92:58987 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.9.96:49559 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.8.197:58838 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.8.248:19745 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.9.208:40599 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.11.212:28493 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.9.20:59951 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.9.158:45795 SYN_RECV
tcp 0 0 aa.bb.cc.dd:443 xxx.189.10.59:26735 SYN_RECV
(以下省略)
(いつもは LISTEN、ESTABLISHED、TIME_WAIT くらいしか存在しないと思います)
攻撃をまさに受けている時の注意点として、 -n オプションを忘れずに。
これを付けないとIPアドレス1つ1つに対して名前解決が発生して、動作がとても重くなってしまうからです。
定期的に確認したいなら、cron とかで5分おきに起動してログに残して、翌日に確認すれば良いと思います。
# あらかじめ mkdir /var/log/netstat した状態で
*/5 * * * * \netstat -tan > /var/log/netstat/log`date +\%H%M`.txt
(netstat のまえにバックスラッシュ \ を付けているのは、alias とかを無効化する小細工です)
もっと本格的に監視したり対策したりするなら、netstat は動作が重いコマンドになります。
(実行に5分以上かかるのも珍しくない、特に攻撃を受けている時は)
その場合は、他のシステムコールや /proc から直に情報を集めるスクリプトを作ることも検討すると良いでしょう。
ケース3:通信の総量から確認するなら†
きりがないので、ひとまずこれで最後ですが、
送受信量はsarコマンドからも取得できます。
何が取得できるかは man sar を参照。たとえば"sar -n DEV" とか。(グラフ化についてはこっちでメモします)
sar以外でも何でも、とにかく通信量やらCPU使用率やらを一定周期で取得しておくと、なんか有った時になんか分かります
取得周期は短めに設定しないと、
瞬間的なアクセス数の増大が検知できないので注意しましょう。
たとえば一時間おきだと、1分間集中砲火を受けて、59分間無風状態なら、平均値からは異常が見えません。
自分の感想だと、5秒毎とか短い数値でも困ったことはありません。
実際にそれぞれの環境で動かして、OS全体やプロセス単位の負荷(psコマンド等で見れます)を確認・調整したほうが早いでしょう。
どれが正規で、どれが非正規の通信か?†
送信元IPが詐称されたものか、本物だけど単に通信を途中で切断しただけなのか、
(Webブラウザを途中で閉じたり、Wi-Fiが途中で切れたり)
1つ1つの通信が本来のものなのか、攻撃目的のものなのかは、見分けるのが困難だと思います。
お店に、正規の客と、嫌がらせの客の両方を大量に送り込むようなものです。
営業妨害(DoS攻撃)するのって簡単ですよね...もちろん、やったらダメですが。
とはいえ、明らかに攻撃と分かるケースとしては...
- telnetやssh、pop3やimapの接続が海外から来るわけはありません。*2
とりあえず "dig -x 送信元IP" で確認してみましょう。
国の内外は参考情報に過ぎませんが
(国内のプロキシサーバを経由すれば、国内アクセスになるので)
それにしても海外からの攻撃は多いので、目安の1つにするのはアリだと思います。
- 前述のように、送信元ポートがsshやら、httpやらのwell-knownポートなわけもありません。
- DoS攻撃だと明らかに異常な接続数なので、すぐに解ると思います。
- Webサーバのリンクを自動巡回するツールとかで一斉にアクセスする場合もあるかもしれませんが、それも量が多ければ DoS攻撃と変わらないので、阻止する方向で検討しても良いかと。
- ただし、自分のWebサイトの構成は確認しましょう。
1つのページに大量の画像リンクとか貼っていれば、当然アクセス数が増えるので。
そして、対策の例としては
まめにファイアウォールで防ごう、ってだけの話にはなってしまいますが...
- 詐称された送信元IPからのアクセスを止める場合、
どこかのタイミングで「解除」が必要なのはお忘れなく。
(たとえば携帯各社のIPを詐称してきたとき、それを止めると、携帯からアクセスできなくなる)
一時的に止める(そして解除)or 長期的に止める、は使い分けることになります。
- 送信元IPが偏っている場合は
個々のIPではなく、適当なサブネット単位で阻止することも考えましょう。
(あとで解除する前提なら、ある程度一気に止めてしまって良いんじゃないかな...?)
- 大量のログやらIPアドレスやらに対しての設定&解除は、手動では無理です。
適宜スクリプト化、ツール化していきましょう。
- 初見だと、大量のDoS攻撃アクセスに引くと思いますが、
企業相手の標的型攻撃ならともかく、大半はbotが雑に(数万の標的の1つとして?)アクセスしてきているだけ、だと思うので、
落ち着いて、できるところから少しずつ対応していきましょう。
firewall-cmdなどで、IPアドレスのリストに対して接続拒否する例はこちら。
大量のSynフラッドを自動検出&接続拒否したい場合は Synフラッドをサブネット単位で防ぐ方法。
いずれにしても、有事にそなえてnetstatコマンドや各種ログから対象のIPアドレスを一気に抜き取る方法には慣れておいたほうが良いと思います。(awk? perl? ruby? python?)
止める効果†
結局、攻撃側も効率よく攻撃しなければならないので、弱いサーバほど狙われることになります。
つね日頃から、どこかの企業やら敵国やらを攻撃するために利用できそうなサーバを、24時間365日ずっと世界中から探して回っているのだと思います。
いくらbotで巡回するにしても、世界中を片っ端から攻撃して反応を見ていかなければならないのだから、時間も予算も無駄にはできない。*3
だから「攻撃に弱いサーバ」はしっかり記録されて、たびたび利用されることになるのでしょう。
そういう意味では大企業より、個人や中小企業のような防御力の低いサーバの方が「踏み台」として利用しやすかろう、と。
そうやって、あらかじめ調査しておいた弱いサーバ一覧を、有事の際に一気に「踏み台として使って」どこかを攻撃するのでしょうね。
だから「弱いサーバ」にカウントされないように、日頃からできるだけ攻撃は防いでおいて「面倒なサーバ」だと思わせておいた方が良いと思います。
実際、まめに攻撃を止めたほうが、徐々に攻撃の頻度も減っていきます。
ぜんぶは無理でも、可能なところから少しずつ対策していきましょう。