iptablesで特定ユーザ以外のSMTP通信をブロックし、SPAMの踏み台になるのを防ぐ方法

サーバに侵入されてしまった時、非常によくあるのが「SPAMの踏み台にされる」ことです。

運良く(運悪く?)SPAMをバラ撒いているプログラムを発見出来ればいいのですが、「SPAMの踏み台にされている疑いがある 1が、そのプログラムは特定出来ない」というのが一番嫌なケースかもしれません。

なぜこのようなことが起こるのかと言うと、次のような2つの問題があるからです。

  1. すべてのユーザが外部のTCP 25番ポートに通信出来てしまう。
  2. ユーザが外部と通信した時のログが残らない。

この2点を解決すれば、

  1. PostfixやSendmailなどの、限られたMTAのみが外部のTCP 25番ポートと通信出来る。MTA経由でSPAMが送信されるリスクは残るが、ログは残るので追跡は可能になる。
  2. ユーザが外部と通信したログが残れば、万が一SPAMをバラ撒くプログラムが存在した時に探す手掛りになる。

ということで、SPAMをバラ撒くリスクを減らしつつ、問題を特定する可能性を高くすることが出来ます。

Linuxの iptables では、

  1. 特定のユーザからの通信のみを許可する
  2. 通信のログを取る

の2点が可能なので、「MTA以外のプログラムが外部のTCP 25番ポートと通信するのをブロックし、ブロックした通信のログを取る」方法を解説します。

前提と環境

この記事は、CentOS の以下のバージョンで動作確認してあります。

  • CentOS 5.11 (iptables v1.3.5)
  • CentOS 6.6 (iptables v1.4.7)

また、MTAとしてはpostfixを想定します。

CentOS 7 の firewalld ですが、ちょっと調べた限りではユーザIDを元にフィルタリングをすることは出来ないようです。もし CentOS 7 でこの記事にある内容を実現するには、firewalld を無効化して iptables を使う必要があるかもしれませんが、この点は未検証です。

iptablesの設定

ユーザIDによるパケットのフィルタリング

ユーザIDを元にパケットのフィルタリングをするには、iptablesの “owner” モジュールを使います。

“owner” モジュールは下記のオプションを取り、ユーザID以外にもグループID、プロセスIDなどでパケットをフィルターすることが出来ます。

–uid-owner userid
実効ユーザIDが userid であるプロセスが生成したパケットにマッチ
–gid-owner groupid
実効グループIDが groupid であるプロセスが生成したパケットにマッチ
–pid-owner processid
プロセスIDが processid であるプロセスが生成したパケットにマッチ
–sid-owner sessionid
セッションIDが sessionid であるプロセスが生成したパケットにマッチ
–cmd-owner name
コマンド名が name であるプロセスが生成したパケットにマッチ

なお、CentOS 5 の iptables の man によると、useridgroupid はそれぞれユーザID、グループIDしか受け付けないように書かれていますが、ユーザ名、グループ名を指定しても動くようです。

また、CentOS 6 の iptables では、useridgroupid に範囲を指定することが出来ます。例えば、--uid-owner 1000-9999 と指定すると、ユーザID 1000 のユーザからユーザID 9999のユーザまでにマッチします。

以上を考慮して、「postfixユーザが生成したパケットが外部のTCP 25番と通信するのを許可する」は、以下のようになります。

sudo iptables -A OUTPUT -p tcp -m tcp --dport 25 -m owner --uid-owner postfix -j ACCEPT

なお、”owner”モジュールは OUTPUTチェーンでしか使えません。

ログの出力

ログを出力するには、”LOG”ターゲットを使います。LOGターゲットは以下のオプションを受け付けます。

–log-level level
ログレベル(syslogのログレベルと同じ)
–log-prefix prefix
ログメッセージの先頭に prefix を付ける
–log-tcp-sequence
TCP のシーケンス番号を出力
–log-tcp-options
TCP オプションを出力
–log-ip-options
IP オプションを出力
–log-uid
パケットを生成したプロセスのユーザIDを出力

iptablesの基本動作は「マッチするルールが存在したら、指定したターゲットに処理を移し、そのチェーンでの処理を終了する」なんですが、マッチしたルールのターゲットが “LOG” だった場合にはそのチェーンでの処理は続きます。従って、「マッチしたパケットのログを取得してから拒否する」という場合には、ログを出力させるルールの後に、「パケットをDROPまたはREJECTする」というルールを書く必要があります。

以上を考慮すると、「postfixユーザ以外が生成したTCP 25番宛のパケットのログを記録し、拒否する」というルールは以下のようになります。

sudo iptables -A OUTPUT -p tcp -m tcp --dport 25 -m state --state NEW -j LOG --log-uid
sudo iptables -A OUTPUT -p tcp -m tcp --dport 25 -j DROP

動作確認

以上で iptables の設定は完了ですが、次は期待した通りの動作をするかどうかを確認します。

postfixユーザ以外が外部のTCP 25番ポートに通信出来ないことの確認

まず、サーバにログインしているユーザで外部のメールサーバと直接通信し、接続出来ないことを確認してみます。外部のサーバと通信するには、telnet または nc を使うと良いでしょう。

telnetの場合:

$ telnet mail.examples.jp 25
Trying ***.***.***.***...

ncの場合:

$ nc mail.examples.jp 25
(応答なし)

上記のように応答がなければ、iptablesの設定はちゃんと出来てると思って良いでしょう。

この場合、/var/log/messages に以下のようなログが残っていると思います。

Jan  2 16:00:49 hogehost kernel: IN= OUT=eth0 SRC=*.*.*.* DST=*.*.*.* LEN=60 TOS=0x10 PREC=0x00 TTL=64 ID=49812 DF PROTO=TCP SPT=58389 DPT=25 WINDOW=5840 RES=0x00 SYN URGP=0 UID=2000

逆に、以下のように応答が返って来る時は、どこか設定に失敗しています。

telnetの場合:

$ telnet mail.examples.jp 25
Trying ***.***.***.***...
Connected to mail.examples.jp (***.***.***.***)
Escape character is '^]'.
220 mail.examples.jp ESMTP Postfix

ncの場合:

$ nc mail.examples.jp 25
220 mail.examples.jp ESMTP Postfix

postfix が外部のTCP 25番ポートと通信出来ていることの確認

次に、postfix が外部のTCP 25番ポートと通信出来ていることの確認です。これは postfix にメールを渡し、ログを確認して外部に送信出来ていることを確認すれば良いでしょう。

例えば mail コマンドを実行し、

$ echo test | mail fuga@examples.com

/var/log/maillog に以下のようなログが残っていれば送信に成功しています。

Jan  2 14:39:18 mail postfix/pickup[23828]: 74A7B4A0056: uid=2000 from=<hoge>
Jan  2 14:39:18 mail postfix/cleanup[25450]: 74A7B4A0056: message-id=<20150102053918.74A7B4A0056@mail.examples.jp>
Jan  2 14:39:18 mail postfix/qmgr[2133]: 74A7B4A0056: from=<hoge@examples.jp>, size=716, nrcpt=1 (queue active)
Jan  2 14:39:18 mail postfix/smtp[25452]: 74A7B4A0056: to=<fuga@examples.com>, relay=mail.examples.com[***.***.***.***]:25, delay=3.1, delays=2.9/0.01/0.03/0.15, dsn=2.0.0, status=sent (250 2.0.0 t025dIkB092634 Message accepted for delivery)
Jan  2 14:39:18 mail postfix/qmgr[2133]: 74A7B4A0056: removed

設定の保存

動作確認が出来たら、iptablesの設定を保存します。デフォルトでは iptables の設定は保存されず、再起動時には変更が元に戻されてしまうので、忘れずに保存しておきましょう。 2

iptables の保存は以下のコマンドで出来ます。

$ /sbin/service iptables save

成功すると、設定が /etc/sysconfig/iptables に書かれるのでチェックします。

$ sudo cat /etc/sysconfig/iptables

Notes:

  1. 例えばブラックリストに掲載されたとか、特定のサイトにメールを拒否されるなど。
  2. シャットダウン時に iptables の設定を保存する設定も出来るのですが、不意の電源断等もあるので、手動で保存するのを忘れない方が良いです。
スポンサーリンク
スポンサーリンク:

フォローする