|
ログインまたはアカウント作成でアカウントを作成すると、編集することができます。 |
DenyHosts で ssh ブルートフォースアタック対策
出典: maruko2 Note.
sshd のログファイル(/var/log/secure など)を定期的に読み込み、sshd の認証に失敗した回数がしきい値(設定した回数)をこえると、/etc/hosts.deny にアクセス拒否の設定を書き込み、接続できないようにする Python のスクリプトです。
- Web Site
- http://denyhosts.sourceforge.net/
目次 |
Mac OS X 10.3/10.4 にインストールする
- python 2.3 以上が必要(インストール済み)
- ソースコード
http://jaist.dl.sourceforge.net/sourceforge/denyhosts/DenyHosts-2.6.tar.gz
1. 解凍・展開しインストール
$ tar xzf DenyHosts-2.6.tar.gz $ cd DenyHosts-2.6 $ sudo python setup.py install
2. /usr/share/denyhosts/ に設定ファイル denyhosts.cfg と、DenyHosts をデーモンとして動作させるスクリプト daemon-control がインストールされる。ファイル名の末尾が -dist になっているので、コピーして使用する。((ディストリビューションや OS の違いで、ログファイルの場所が違ったりするため。))
$ cd /usr/share/denyhosts $ sudo cp daemon-control-dist daemon-control $ sudo cp denyhosts.cfg-dist denyhosts.cfg
3. Mac OS X には、デフォルトで /etc/host.deny /etc/hosts.allow ファイルがないので作っておく。
$ sudo touch /etc/{hosts.deny,hosts.allow}
4. 設定ファイル denyhosts.cfg を Mac OS X 用に修正 ((denyhosts.cfg に Mac OS X の設定例が書かれているが、それとは違う設定にする。))
SECURE_LOG = /var/log/system.log ← Mac OS X 10.3 の場合 SECURE_LOG = /var/log/secure.log ← Mac OS X 10.4 の場合 LOCK_FILE = /var/run/denyhosts.pid ← Mac OS X 10.3/10.4 共通 DAEMON_LOG = /var/log/denyhosts.log ← Mac OS X 10.3/10.4 共通
5. daemon-control を Mac OS X 用に修正
DENYHOSTS_BIN = "/System/Library/Frameworks/Python.framework/Versions/2.3/bin/denyhosts.py" DENYHOSTS_LOCK = "/var/run/denyhosts.pid"
これで、インストール完了。
デーモンとして起動
$ sudo /usr/share/denyhosts/daemon-control start
ログが大きいと少し時間がかかるかもしれない。
ログの読み込みが完了すると、デーモンとして起動したままになる。
読み込まれ、解析されたデータは、/usr/share/denyhosts/data/ ディレクトリ内に保存される。
/var/log/denyhosts.log で動作確認
denyhosts.log の内容はこんな感じ。
2007-06-02 14:46:53,749 - denyhosts : INFO DenyHosts launched with the following args: 2007-06-02 14:46:53,751 - denyhosts : INFO /System/Library/Frameworks/Python.framework/Versions/2.3/bin/denyhosts.py --daemon --config=/usr/share/denyhosts/denyhosts.cfg 2007-06-02 14:46:53,752 - prefs : INFO DenyHosts configuration settings: 省略
すでに、ブルートフォースアタックがあった場合は、次のように記録される。
2007-06-04 18:09:52,474 - denyhosts : INFO new denied hosts: ['219.232.237.39']
そして、/etc/hosts.deny に次のような記述が追加され、sshd への接続を拒否するようになる。
sshd: 219.232.237.39
logrotate している場合どうなるのか
ログを読み込み終わると、data/offset にログの読み込み済みの位置を書き込んで、次回はその位置以降から読み込むようにしている。 ローテートされるログでも問題なく動作する。
2007-06-04 03:15:12,442 - denyhosts : INFO /var/log/system.log has been rotated
denyhosts.cfg の設定
- SECURE_LOG = /var/log/secure.log
- denyhosts の読み込むログファイルの場所
- HOSTS_DENY = /etc/hosts.deny
- hosts.deny の場所
- PURGE_DENY =
- 拒否するホストを /etc/hosts.deny に登録しておく時間を設定する(この設定時間を過ぎると、拒否するホストから削除される。)
- 空白の場合は、ずっと登録したままにになる。
-
--purge オプションを付けてスクリプトを起動しないと実行しない。
- #PURGE_THRESHOLD
- 拒否するホストを /etc/hosts.deny から削除する最大回数を定義する。この回数を超えると、/etc/hosts.deny に登録されたままになる。default 0 (disable)
- BLOCK_SERVICE = sshd
- /etc/hosts.deny に追加するときのサービス名。
- DENY_THRESHOLD_INVALID = 5
- この回数より多くログインに失敗したホストをブロックする。存在しないユーザに適用。
- DENY_THRESHOLD_VALID = 10
- この回数より多くログインに失敗したホストをブロックする。存在するユーザに適用。root は除く。
- DENY_THRESHOLD_ROOT = 1
- この回数より多くログインに失敗したホストをブロックする。root のみ。
- DENY_THRESHOLD_RESTRICTED = 1
- この回数より多くログインに失敗したホストをブロックする。WORK_DIR/restricted-usernames ファイルに書かれている username のみ。
- WORK_DIR = /usr/share/denyhosts/data
- WORK_DIR のパス。
- SUSPICIOUS_LOGIN_REPORT_ALLOWED_HOSTS=YES
- YES に設定している場合、許可されたホストからの疑わしいログインを、疑わしいログインとしてレポートする。
- NOに設定している場合、レポートしない。許可されたホストでない疑わしいログインは、全てレポートする。
- HOSTNAME_LOOKUP=YES
- YES なら、IP アドレスからホスト名をルックアップする。
- LOCK_FILE = /var/run/denyhosts.pid
- LOCK_FILE を指定する。
optional setting
- ADMIN_EMAIL =
- 新しい拒否するホストと疑わしいログインについてメールする。
- SMTP_HOST = localhost
- SMTP サーバのアドレス。
- SMTP_PORT = 25
- SMTP サーバのポート。
- #SMTP_USERNAME=foo
- SMTP 認証で使用するユーザ名。
- #SMTP_PASSWORD=bar
- SMTP 認証のパスワード。
- SMTP_FROM = DenyHosts <nobody@localhost>
- メールの From: アドレス。
- SMTP_SUBJECT = DenyHosts Report
- メールの件名。
- #SMTP_DATE_FORMAT = %a, %d %b %Y %H:%M:%S %z
- メールの Date: の書式。
- #SYSLOG_REPORT=NO
- syslog へデータを送るかどうか。
- #ALLOWED_HOSTS_HOSTNAME_LOOKUP=NO
- AGE_RESET_VALID=5d
- AGE_RESET_ROOT=25d
- AGE_RESET_RESTRICTED=25d
- AGE_RESET_INVALID=10d
- #RESET_ON_SUCCESS = yes
- #PLUGIN_DENY=/usr/bin/true
- #PLUGIN_PURGE=/usr/bin/true
- #USERDEF_FAILED_ENTRY_REGEX=
daemonmode setting
- DAEMON_LOG = /var/log/denyhosts.log
- #DAEMON_LOG_TIME_FORMAT = %b %d %H:%M:%S
- DAEMON_LOG_MESSAGE_FORMAT = %(asctime)s - %(name)-12s: %(levelname)-8s %(message)s
- DAEMON_SLEEP = 30s
- デーモンモードで実行中、SECURE_LOG を読みにいくまでのスリープしている時間。
- DAEMON_PURGE = 1h
- /etc/host.deny の中の過ぎたエントリーをパージする間隔。PURGE_DENY が空のときはなにもしない。
daemon sync setting
- #SYNC_SERVER = http://xmlrpc.denyhosts.net:9911
- #SYNC_INTERVAL = 1h
- #SYNC_UPLOAD = no
- #SYNC_DOWNLOAD = no
- #SYNC_DOWNLOAD_THRESHOLD = 10
- #SYNC_DOWNLOAD_RESILIENCY = 2d
起動スクリプト
/Library/StartupItems/DenyHosts/DenyHosts
#!/bin/sh
. /etc/rc.common
StartService ()
{
if [ "${DenyHosts:=-NO-}" = "-YES-" ] ; then
ConsoleMessage "Starting DenyHosts"
/usr/share/denyhosts/daemon-control start >/dev/null 2>&1
fi
}
StopService ()
{
if [ "${DenyHosts:=-NO-}" = "-YES-" ] ; then
ConsoleMessage "Stopping DenyHosts"
/usr/share/denyhosts/daemon-control stop >/dev/null 2>&1
fi
}
RestartService ()
{
if [ "${DenyHosts:=-NO-}" = "-YES-" ] ; then
ConsoleMessage "Starting DenyHosts"
/usr/share/denyhosts/daemon-control restart >/dev/null 2>&1
fi
}
RunService "$1"/Library/StartupItems/DenyHosts/StartupParameters.plist
{
Description = "DenyHosts";
OrderPreference = "Last";
Messages =
{
start = "Starting DenyHosts";
stop = "Stopping DenyHosts";
};
}/etc/hostconfig に DenyHosts=-YES- を追加
ホワイトリスト (Whitelist)
常に許可するホストのリスト。
/etc/hosts.allow に許可するアドレスを書いておく。hosts.allow にリストされたアドレスは、hosts.deny に追加されても許可される。
- /etc/hosts.allow の例
IPアドレス 192.168.1.0〜192.168.1.254 のホストからの sshd への接続を常に許可する。
sshd: 192.168.1.
- denyhosts.py --help [#xc1c15e6]
$ denyhosts.py --help
Usage:
/System/Library/Frameworks/Python.framework/Versions/2.3/bin/denyhosts.py [-f logfile | --file=logfile] [ -c configfile | --config=configfile] [-i | --ignore] [-n | --noemail] [--purge] [--migrate] [--daemon] [--sync] [--version]
--file: The name of log file to parse
--ignore: Ignore last processed offset (start processing from beginning)
--noemail: Do not send an email report
--unlock: if lockfile exists, remove it and run as normal
--migrate: migrate your HOSTS_DENY file so that it is suitable for --purge
--purge: expire entries older than your PURGE_DENY setting
--daemon: run DenyHosts in daemon mode
--sync: run DenyHosts synchronization mode
--version: Prints the version of DenyHosts and exits
Note: multiple --file args can be processed. If multiple files are provided, --ignore is implied
When run in --daemon mode the following flags are ignored:
--file, --purge, --migrate, --sync, --verbose
その他
Mac OS X にインストールされている Python
- PYTHONHOME
/System/Library/Framework/Python.framework/Versions/2.3/
- PYTHONPATH
/System/Library/Frameworks/Python.framework/Versions/2.3/bin/python /usr/bin/python シンボリックリンク
- site-packages
/Library/Python/2.3/site-packages
インストールされるファイル
- lib site-packages/DenyHosts/ __init__.py __init__.pyc allowedhosts.py allowedhosts.pyc constants.py constants.pyc counter.py counter.pyc daemon.py daemon.pyc deny_hosts.py deny_hosts.pyc denyfileutil.py denyfileutil.pyc filetracker.py filetracker.pyc lockfile.py lockfile.pyc loginattempt.py loginattempt.pyc old-daemon.py old-daemon.pyc plugin.py plugin.pyc prefs.py prefs.pyc purgecounter.py purgecounter.pyc python_version.py python_version.pyc regex.py regex.pyc report.py report.pyc restricted.py restricted.pyc sync.py sync.pyc util.py util.pyc version.py version.pyc - script bin/denyhosts.py - data /usr/share/denyhosts denyhosts.cfg-dist setup.py daemon-control-dist CHANGELOG.txt README.txt LICENSE.txt /usr/share/denyhosts/scripts restricted_from_invalid.py restricted_from_passwd.py /usr/share/denyhosts/plugins README.contrib shorewall_allow.sh shorewall_deny.sh test_deny.py
ログの読み込みパターン
regex.py に書かれている。
regex.py の一部
SSHD_FORMAT_REGEX = re.compile(r""".* (sshd.*:|\[sshd\]) (?P<message>.*)""")
FAILED_ENTRY_REGEX = re.compile(r"""Failed (?P<method>.*) for (?P<invalid>invalid user |illegal user )?(?P<user>.*?) .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
FAILED_ENTRY_REGEX2 = re.compile(r"""(?P<invalid>(Illegal|Invalid)) user (?P<user>.*?) .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
FAILED_ENTRY_REGEX3 = re.compile(r"""Authentication failure for (?P<user>.*) .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
FAILED_ENTRY_REGEX4 = re.compile(r"""Authentication failure for (?P<user>.*) .*from (?P<host>.*)""")
FAILED_ENTRY_REGEX5 = re.compile(r"""User (?P<user>.*) .*from (?P<host>.*) not allowed because none of user's groups are listed in AllowGroups""")
FAILED_ENTRY_REGEX6 = re.compile(r"""Did not receive identification string .*from (::ffff:)?(?P<host>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})""")
FAILED_ENTRY_REGEX7 = re.compile(r"""User (?P<user>.*) not allowed because not listed in AllowUsers""")追加するときは、denyhosts.cfg に SSHD_FORMAT_REGEX = で追加することもできる。
