サーバセキュリティ ufw, Fail2Ban

注) tinyhoneypotと組合せて使用する必要はもうなさそうです。

fail2banは不正アクセス履歴のあるIPアドレスを拒絶するファイヤーウォールです。設定ファイルの項目を見直すことで、より細かいフィルタリングができます。

tinyhoneypotはTCP/IP各ポートを監視し、アクセス元の詳細を記録します。
xinetdによりtinyhoneypotが動作、tinyhoneypotによる指定ポートを巧みに操作します。

まず、上記ソフトをインストールします。

sudo apt-get install tinyhoneypot fail2ban xinetd

設定

SSHの標準ポート番号を以下のコマンドで書換えます。

sudo sed -i.orig ‘s/Port 22/Port 2201/m’ /etc/ssh/sshd_config

/etc/ssh/sshd_configのSSHポートは22から2201に書換えられ、オリジナルは /etc/ssh/sshd_config.origとして保存されます。

SSHを再起動し、SSHのポート番号が変更されているかどうか確認して下さい。

sudo service ssh restart
sudo netstat -lptn | grep ssh

tcp 0 0 0.0.0.0:2201 0.0.0.0:* LISTEN 4313/sshd
tcp6 0 0 :::2201 :::* LISTEN 4313/sshd

xinetdの設定ファイルを作成、tinyhoneypotを起動しTCPのポート番号22を開放します。

sudo cp -v /usr/share/doc/tinyhoneypot/examples/xinetd.d/thp-pasv /etc/xinetd.d/

/etc/xinetd.d/thp-pasv を次のように編集します:

sudo pico /etc/xinetd.d/thp-pasv

  # default: on
  # description: thp-ftpd calls the generic thpsvcs with param "ftp",
  #       resulting in an ftpd emulation.

service thp-pasv
{
        type                    = UNLISTED
        socket_type             = stream
        protocol                = tcp
        port                    = 22
        wait                    = no
        user                    = thpot
        server                  = /usr/sbin/thpot
        server_args             = nullresp
        nice                    = 10
        disable                 = no
        instances               = 1
        per_source              = 1

}

xinetdを再起動してポート番号22が開放されているか確認します。

sudo service xinetd restart
sudo netstat -lptn | grep xinetd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 4567/xinetd

tinyhoneypotの動作確認

他のPCからSSHアクセスを試みます。

attacker@hackerpc:~$ ssh 192.168.88.212

何も表示されないので[Ctrl + C]を押して終了します。

アクセスログを確認します。

sudo cat /var/log/thpot/captures
Feb 29 13:02:10 SID=56D4334221165.nullresp PID=4837 SRC=192.168.88.242 SPT=47187 ET=00:00:11 BYTES=39

次のfail2banでこのログを参照することにより、SRCのIPアドレスからのアクセスを拒否します。

fail2banの設定

sudo cd /etc/fail2ban/
sudo cp -v jail.conf jail.local

jail.confは編集しないで下さい。jail.localにより設定事項を調整します。

[sshd]のセクションを以下のようにします。 2201は /etc/ssh/sshd_config で変更したポート番号です。

jail.localのjailセクションの箇所に入力して下さい。

[ssh]
enabled  = true
port     = 2201
filter   = sshd
logpath  = /var/log/auth.log
maxretry = 6

次の[thp-ssh]セクションを追加します。fail2banがtinyhoneypotのログファイルを参照し、特定IPアドレスのアクセスを拒否する設定です。

[thp-ssh]
enabled  = true
port     = all
filter   = thpot
logpath  = /var/log/thpot/captures
banaction = iptables-allports
maxretry = 3
findtime = 1800
bantime = 99999

fail2banがログの中のアクセス元を特定するため、フィルターファイルが必要となります。以下作成します。

sudo pico /etc/fail2ban/filter.d/thpot.local

[Definition]
failregex = SRC=<HOST>
ignoreregex =

次に、fail2banを再起動して以下の動作確認をするのですが、ここでfail2banのロケール問題が発生するかもしれません。(サーバロケールが日本語の場合など)サーバロケールが英語であれば何も問題がないのですが、タイムスタンプが日本語だとログを読み取ってくれません。そこでロケールのLC_TIMEのフォーマットをPOSIXにします。

https://help.ubuntu.com/community/Locale

sudo pico /etc/default/locale

LANG=ja_JP.UTF-8
LC_TIME=POSIX

とし、サーバを再起動して下さい。

ロケールの見直しが不要であれば、fail2banを再起動します。

sudo service fail2ban restart

var/log/fail2ban.logを確認します。

2016-02-29 13:54:06,915 fail2ban.jail   [6102]: INFO    Creating new jail 'thp-ssh'
2016-02-29 13:54:06,915 fail2ban.jail   [6102]: INFO    Jail 'thp-ssh' uses pyinotify
2016-02-29 13:54:06,920 fail2ban.jail   [6102]: INFO    Initiated 'pyinotify' backend
2016-02-29 13:54:06,922 fail2ban.filter [6102]: INFO    Added logfile = /var/log/thpot/captures
2016-02-29 13:54:06,923 fail2ban.filter [6102]: INFO    Set maxRetry = 1
2016-02-29 13:54:06,925 fail2ban.filter [6102]: INFO    Set findtime = 1800
2016-02-29 13:54:06,926 fail2ban.actions[6102]: INFO    Set banTime = 99999
2016-02-29 13:54:06,934 fail2ban.jail   [6102]: INFO    Jail 'ssh' started
2016-02-29 13:54:06,940 fail2ban.jail   [6102]: INFO    Jail 'thp-ssh' started

必要であれば以下有効時間の設定を見直してみて下さい。

findtime = 1800
bantime = 99999

iptablesのルールを確認します。

sudo iptables-save

# Generated by iptables-save v1.4.21 on Mon Feb 29 14:05:17 2016
*filter
:INPUT ACCEPT [2:64]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:fail2ban-ssh - [0:0]
:fail2ban-thp-ssh - [0:0]
-A INPUT -p tcp -j fail2ban-thp-ssh
-A INPUT -p tcp -m multiport --dports 2201 -j fail2ban-ssh
-A fail2ban-ssh -j RETURN
-A fail2ban-thp-ssh -j RETURN
COMMIT
# Completed on Mon Feb 29 14:05:17 2016

他のPCから拒否されるか実際に確認してみます。

ssh 192.168.88.212

^C

ssh 192.168.88.212

ssh: connect to host 192.168.88.212 port 22: Connection refused

最初のコマンドでは何も起こりません。[Ctrl+C]で終了します。次のssh接続で拒否されるメッセージが表示されます。

iptablesのルールをもう一度確認します。

sudo iptables-save

# Generated by iptables-save v1.4.21 on Mon Feb 29 14:10:53 2016
*filter
:INPUT ACCEPT [4:542]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1:88]
:fail2ban-ssh - [0:0]
:fail2ban-thp-ssh - [0:0]
-A INPUT -p tcp -j fail2ban-thp-ssh
-A INPUT -p tcp -m multiport --dports 2201 -j fail2ban-ssh
-A fail2ban-ssh -j RETURN
-A fail2ban-thp-ssh -s 192.168.88.242/32 -j REJECT --reject-with icmp-port-unreachable
-A fail2ban-thp-ssh -j RETURN
COMMIT
# Completed on Mon Feb 29 14:10:53 2016

アクセス元PCのIPアドレスが拒否されています。

間違ってリジェクトされたIPをリストから削除します。

# sudo iptables-save
-A f2b-ssh -j RETURN
-A f2b-sshd -j RETURN
-A f2b-thp-ssh -s 192.168.10.10/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-thp-ssh -j RETURN
COMMIT
# Completed on Thu Oct  6 13:43:38 2016

上記リストから192.168.10.10/32を削除するには、

# sudo iptables -D f2b-thp-ssh -s 192.168.10.10/32 -j REJECT

ジャイルされたIPの確認

$ sudo iptables -n -L

ジャイル名の確認

$ sudo fail2ban-client status
Status
|- Number of jail:	3
`- Jail list:	ssh, sshd, thp-ssh

ジャイル解除

fail2ban-client set yourjailname unbanip youripaddress

$ sudo fail2ban-client set ssh unbanip 10.xx.15x.12x
$ sudo fail2ban-client set sshd unbanip 10.xx.15x.12x
$ sudo fail2ban-client set thp-ssh unbanip 10.xx.15x.12x

ufw (Uncomplicated Firewall)

nftablesによるセキュリティ設定を以下のufwコマンドで容易に行えます。デフォルトでは非アクティブです。

ドキュメント

UFW - Community Help Wiki
Uncomplicated Firewall - ArchWiki

セットアップ例

How To Setup a Firewall with UFW on an Ubuntu and Debian Cloud Server

UFW Essentials: Common Firewall Rules and Commands

ステータス確認

$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----

まずは ssh のポート許可のルールを追加します。ルールの追加は ufw が非アクティブな状態でも行えます。 ssh のデフォルトポートを変更している場合は直接ポート番号を指定します。プロトコルを指定する場合はポート番号に /tcp,/udp などを追加します。

sshの許可

$ sudo ufw allow ssh

http.httpsの許可

$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp

SSH接続許可をローカルIPからに制限

$ sudo ufw allow from 203.0.113.103 proto tcp to any port 22

その他外部からのアクセスに必要なポートを許可して下さい。

アクティブ

$ sudo ufw enable 

非アクティブ

$ sudo ufw disable 

ルール確認

$ sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22                      ALLOW IN    Anywhere                  
[ 2] 80                         ALLOW IN    Anywhere                  
[ 3] 443                        ALLOW IN    Anywhere                  
[ 4] 22 (v6)                 ALLOW IN    Anywhere (v6)             
[ 5] 80 (v6)                    ALLOW IN    Anywhere (v6)             
[ 6] 443 (v6)                   ALLOW IN    Anywhere (v6) 

ルールの削除

上記リスト番号を指定して削除

$ sudo ufw delete 3

リセット

リセット時の設定はバックアップされ、ufwが非アクティブになります。

$ sudo ufw reset
インストール時のデフォルトルールを再設定します。操作を続行しますか (y|n)? y
'user.rules'から'/etc/ufw/user.rules.20230613_150003'にバックアップしています
'before.rules'から'/etc/ufw/before.rules.20230613_150003'にバックアップしています
'after.rules'から'/etc/ufw/after.rules.20230613_150003'にバックアップしています
'user6.rules'から'/etc/ufw/user6.rules.20230613_150003'にバックアップしています
'before6.rules'から'/etc/ufw/before6.rules.20230613_150003'にバックアップしています
'after6.rules'から'/etc/ufw/after6.rules.20230613_150003'にバックアップしています

beforeとafterルールは、直接ファイルを編集・読込することで適用されるルールなので、これらルールを使用していなければ、バックアップファイルから以前の設定を復元するには、

$ sudo cp /etc/ufw/user.rules.20230613_150003 /etc/ufw/user.rules
$ sudo cp /etc/ufw/user6.rules.20230613_150003 /etc/ufw/user6.rules
$ sudo ufw enable
$ sudo ufw reload

リセット後ルール再設定

$ sudo ufw --force reset
$ sudo ufw --force disable
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow proto tcp from 192.168.0.0/24 to any port 80
...
...
$ sudo ufw --force enable

Fail2banアップデート

警告をメール経由で受け取る設定については以下参照のこと。

Nginxへの適用

Fail2banのインストール

$ sudo apt install fail2ban

空のjail.localファイルを作成し、必要なセクションを有効化・編集すること(設定ファイルのコピーはしないこと)

$ sudo nano /etc/fail2ban/jail.local

jail.localファイルでネットワークアクセスのあるサービスのアクセス制限の有効化(enabled = true)、条件を設定

/etc/fail2ban/jail.local

…
[nginx-http-auth]

enabled  = true
port     = http,https
logpath = %(nginx_error_log)s
. . .

サービスの有効化と起動・ステータス確認

$ sudo systemctl enable fail2ban
$ sudo systemctl start fail2ban
$ sudo systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2024-07-09 08:47:35 UTC; 2s ago
       Docs: man:fail2ban(1)
   Main PID: 1323294 (fail2ban-server)
      Tasks: 5 (limit: 9238)
     Memory: 13.1M
        CPU: 174ms
     CGroup: /system.slice/fail2ban.service
             └─1323294 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

以下のfail2banクライアントコマンドで各種条件、banされているIPの確認・削除などが行えます。

$ sudo fail2ban-client --help
Usage: fail2ban-client [OPTIONS] <COMMAND>

Fail2Ban v0.11.2 reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.

Options:
    -c, --conf <DIR>        configuration directory
    -s, --socket <FILE>     socket path
    -p, --pidfile <FILE>    pidfile path
    --pname <NAME>          name of the process (main thread) to identify instance (default fail2ban-server)
    --loglevel <LEVEL>      logging level
    --logtarget <TARGET>    logging target, use file-name or stdout, stderr, syslog or sysout.
    --syslogsocket auto|<FILE>
    -d                      dump configuration. For debugging
    --dp, --dump-pretty     dump the configuration using more human readable representation
    -t, --test              test configuration (can be also specified with start parameters)
    -i                      interactive mode
    -v                      increase verbosity
    -q                      decrease verbosity
    -x                      force execution of the server (remove socket file)
    -b                      start server in background (default)
    -f                      start server in foreground
    --async                 start server in async mode (for internal usage only, don't read configuration)
    --timeout               timeout to wait for the server (for internal usage only, don't read configuration)
    --str2sec <STRING>      convert time abbreviation format to seconds
    -h, --help              display this help message
    -V, --version           print the version (-V returns machine-readable short format)

Command:
                                             BASIC
    start                                    starts the server and the jails
    restart                                  restarts the server
    restart [--unban] [--if-exists] <JAIL>   restarts the jail <JAIL> (alias
                                             for 'reload --restart ... <JAIL>')
    reload [--restart] [--unban] [--all]     reloads the configuration without
                                             restarting of the server, the
                                             option '--restart' activates
                                             completely restarting of affected
                                             jails, thereby can unban IP
                                             addresses (if option '--unban'
                                             specified)
    reload [--restart] [--unban] [--if-exists] <JAIL>
                                             reloads the jail <JAIL>, or
                                             restarts it (if option '--restart'
                                             specified)
    stop                                     stops all jails and terminate the
                                             server
    unban --all                              unbans all IP addresses (in all
                                             jails and database)
    unban <IP> ... <IP>                      unbans <IP> (in all jails and
                                             database)
    banned                                   return jails with banned IPs as
                                             dictionary
    banned <IP> ... <IP>]                    return list(s) of jails where
                                             given IP(s) are banned
    status                                   gets the current status of the
                                             server
    ping                                     tests if the server is alive
    echo                                     for internal usage, returns back
                                             and outputs a given string
    help                                     return this output
    version                                  return the server version
.....
.....

Docker Nginx コンテナ + Fail2ban

以下、ホストマシンと共有したDocker Nginxのログファイルを参照して、Fail2banによるルールをNginxコンテナに適用。

[nginx-http-auth]

enabled  = true
port     = http,https
logpath = /xxx/xxx/container_logs/nginx

注) fail2banの設定を変更する場合は、下記の設定ファイルをコピーして編集するのではなく、*.localを拡張子として空のファイルを作成し設定変更するセクションのみを記述すること。

/etc/fail2ban/fail2ban.conf —> fail2ban.local
/etc/fail2ban/jail.conf —> jail.local

UFW(Uncomplicated Firewall)と iptables-nft / nftables の関係について

「UFWを有効にした状態でnftablesを使用しないこと」

UFW(Uncomplicated Firewall)は内部的にnftablesを操作して動作しています。そのため、nftablesを手動で直接操作したり、システム起動時に自動で有効化してしまうと、UFWによって設定されたルールが上書き・破壊される恐れがあります。
したがって、UFWを使用している場合は、nftablesを直接操作したり有効にしたりしないでください。