それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

OpenVZの仮想サーバ(VE)のSSHポートをiptablesで保護する

これはかなりハマった。

Debian lenny上のopenvzではiptablesのrecentが動かない。

VEにiptablessshアタック防止設定をしようとした。

sudo vzctl enter 1001
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 3 --rttl --name SSH -j DROP

こんなエラーとか出る。

iptables: No chain/target/match by that name

または、こんなエラー

iptables: invalid argument

iptablesエラーメッセージの読み方。

ここのサイトに詳しく載っている。>>12.4. iptablesのデバグ
以下に抜粋を載せる。

通常、カーネルに内蔵済みでないモジュールがあると iptables は自動的に modprobe する能力を持っているので、こうしたエラーの出た原因はふた通り考えられる。カーネルをコンパイルしなおしてから depmod を適切に行わなかったか、あなたがそのモジュールのことをはなから忘れていたかのどちらかだ。ところが一方、問題のモジュールがマッチに関するものだった場合、エラーメッセージはもっと暗号じみて、理解が困難となる。例としてこのエラーメッセージを見ていただこう。

work3:~# iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
iptables: No chain/target/match by that name

(中略)

depmod のし忘れなのかモジュールそのものが欠如しているのかを知る一番手っ取り早い方法は、モジュールが存在するはずのディレクトリを確認してみることだ。

つまり原因はipt_recentモジュールの欠如だが・・・

ここまで原因がつかめてきた。OpenVZのフォーラムなどを読んで大体を理解した。原因はipt_recentの欠如である。そしてOpenVZの仮想サーバー(以下VE)のiptablesはホスト側のモジュールと共有しているらしい。

Matt,


in 2.6.18 kernels we have changed iptables support and now all targets/matches loaded on the node are accessible inside VE.


But all targets and matches should be accessible inside VE, I've checked it on your node:

Re:ipt_recent is now missing?

考えられる原因は二つ

考えられる原因は二つある。ここが重要。

  1. ホスト側にモジュールがロードされていない。
  2. ホスト側のモジュールをopenvzが共有してない。

このそれぞれに対してエラーメッセージは対応している

原因とエラーの対応はこうなる。(かも)
原因 エラーメッセージ
ホスト側にモジュールがロードされていない。 iptables: No chain/target/match by that name
ホスト側のモジュールをopenvzが共有してない。 iptables: invalid argument

なんとなくこんな感じのようだ。

ホストとモジュール共有をしているか?

ここで12.4. iptablesのデバグの記述を振り返ってみよう。

通常、カーネルに内蔵済みでないモジュールがあると iptables は自動的に modprobe する能力を持っているの・・・・(ry

ホスト側でロード済みでないと、VEから使えない。

iptablesはモジュールが自動的にロードされる。しかしVEのiptablesは自分でロードできない。モジュールはホストと共通だからだ。従って『ホスト側にロード済モジュールだけ』がVE側は使用可能。だからホスト側でロードする必要がある。
 さらにOpenVZではVE管理機能(vzctl)がある。この管理機能がVEのiptablesが使えるモジュールを制限することができる。言い換えればホスト側がモジュールロードされていても、VEの設定次第でVEがモジュール使えないことがある。

ホスト側のiptablesのモジュールを確認する。
$> sudo lsmod | grep ipt_recent
 #何もない。。。
$> 

僕の場合はロードされていなかった。そういえばホスト側のiptablesはこのトラブル時にリセットしてから、まだ設定してないんだった。

ホスト側のiptablesを設定する。

通常のiptablesの設定方法。

アクセス数が一定以上なら、sshのポートブロックする。

sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH;\
sudo iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 3 --rttl --name SSH -j DROP
ipt_recentがロードされる。
$> sudo lsmod | grep ipt_r

ipt_recent              8152  2
x_tables               14404  17 xt_DSCP,xt_helper,xt_conntrack,ipt_LOG,xt_length,ipt_ttl,xt_tcpmss,xt_TCPMSS,xt_multiport,xt_limit,xt_dscp,ipt_REJECT,ipt_recent,xt_state,xt_tcpudp,iptable_nat,ip_tables

ちゃんとロードされた。

再起動時にipt_recentがロードされる設定。

iptables設定が再起動後にロードされるようにする。このためにiptablesの設定が自動ロードされるようにする。
OpenVZのホスト側で以下の設定をする。

sudo iptables-save > /etc/iptables.rules
sudo echo '#!/bin/bash
iptables-restore /etc/iptables.rules
' >> /etc/network/if-pre-up.d/iptables
sudo chmod +x /etc/network/if-pre-up.d/iptables
再起動してロードを確認する。
$> sudo reboot
The system is going down for reboot NOW!

$> sudo lsmod | grep ipt_r

ipt_recent              8152  2
x_tables               14404  17 xt_DSCP,xt_helper,xt_conntrack,ipt_LOG,xt_length,ipt_ttl,xt_tcpmss,xt_TCPMSS,xt_multiport,xt_limit,xt_dscp,ipt_REJECT,ipt_recent,xt_state,xt_tcpudp,iptable_nat,ip_tables

ちゃんとロードされた。

OpenVZのVEでモジュールが使えるか調べる。

$> sudo vzctl exec 105 cat /proc/net/ip_tables_matches | grep re
recent

ちゃんとロードされたね。でもまだ、iptablesするまえに行う設定がある。

VEが使えるiptablesモジュールを追加指定する

方法A:OpenVZのVE全部に設定する。

/etc/vz/vz.conf (debian lenny)

#IPTABLESを以下のように書き換え
#IPTABLES="ipt_REJECT ipt_tos ipt_limit ipt_multiport iptable_filter iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length"
#↓↓
IPTABLES="ipt_REJECT ipt_tos ipt_limit ipt_multiport iptable_filter iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length ip_conntrack ip_conntrack_ftp ip_conntrack_irc ipt_LOG ipt_conntrack ipt_helper ipt_state iptable_nat ip_nat_ftp ip_nat_irc ipt_TOS"

centの場合は/etc/sysconfig/vz (たぶん)

方法B:VEごとに設定する。
sudo vzctl set 105 \
 --iptables ipt_REJECT --iptables ipt_tos --iptables ipt_limit --iptables ipt_multiport \
 --iptables iptable_filter --iptables iptable_mangle --iptables ipt_TCPMSS \
 --iptables ipt_tcpmss --iptables ipt_ttl --iptables ipt_length --iptables ip_conntrack \
 --iptables ip_conntrack_ftp --iptables ip_conntrack_irc --iptables ipt_LOG \
 --iptables ipt_conntrack --iptables ipt_helper --iptables ipt_state \
 --iptables iptable_nat --iptables ip_nat_ftp --iptables ip_nat_irc --iptables ipt_TOS \
 --iptables ipt_recent \
 --save

準備ができたらVEを再起動

for i in {101..120} ;do
 sudo vzctl restart $i;
done;

OpenVZのVEにiptablesによるSSH総当たり対策を施す。

sudo vzctl enter 102
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH;
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 3 --rttl --name SSH -j DROP
sudo iptables-save > /etc/iptables.rules
sudo echo '#!/bin/bash
iptables-restore /etc/iptables.rules
' >> /etc/network/if-pre-up.d/iptables
sudo chmod +x /etc/network/if-pre-up.d/iptables
VE再起動後も有効か調べる。
sudo vzctl restart 102
sudo vzctl exec 102 iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
           tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: SET name: SSH side: source
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 3 TTL-Match name: SSH side: source

ちゃんと有効になっており問題なく成功した。

iptablesの使い方。

少し古いけれど、基本的なことはシッカリ載っているので参考に。

http://www.asahi-net.or.jp/~AA4T-NNGK/ipttut/output/index.html