ハニーポット切り替え合理化

海外からのアクセスは、その大半が攻撃やスキャンであるため、ハニーポットへ振り分けるという方針を基本としている。
これまで、主要サーチエンジン以外の海外アクセスについては、下記のように別ホストへ転送していた。

●これまでの振り分けイメージ

Internet
   |
   v
+----------------------------+
|        Router              |
|     iptables / NAT         |
+----------------------------+
   |                      |
   |                      |
 Normal                 Suspicious
 / Allowed              / Unknown
   |                      |
   v                      v
+----------------+   +----------------+
| 192.168.1.1    |   | 192.168.1.2    |
| Main Server    |   | Honeypot       |
+----------------+   +----------------+

従来は、Web以外のプロトコルも含めて転送可能とするため、ハニーポットを別ホストとして分離していた。
しかし最近では、対象をWebアクセスのみに限定しているため、この構成を見直した。
その結果、別ホストを維持するメリットが薄れたため、Apacheのリッスンポートを追加し、単一ホスト上のバーチャルホスト構成でハニーポットを実現する方式へ変更した。

●新しい振り分けイメージ

Internet
   |
   v
+----------------------------+
|        Router              |
|     iptables / NAT         |
+----------------------------+
   |                      |
   |                      |
 Normal                 Suspicious
 / Allowed              / Unknown
   |                      |
   v                      v
+----------------+   +----------------+
| 192.168.1.1:80 |   |192.168.1.1:9080|
| 192.168.1.1:443|   |192.168.1.1:9443|
| Main Server    |   | Honeypot       |
+----------------+   +----------------+

この構成により、物理・仮想ホストの分離を廃しつつ、ポート単位で役割を分離するシンプルな設計となる。
また、ログ管理や証明書運用も一元化できるため、運用負荷の低減にも寄与する。

Apache設定(ports.conf)

Apacheのリッスンポート追加は、以下のように設定するだけでよい。

Listen 80
Listen 9080

<IfModule ssl_module>
    Listen 443
    Listen 9443
</IfModule>

<IfModule mod_gnutls.c>
    Listen 443
    Listen 9443
</IfModule>

※ 9080 / 9443 をハニーポット用ポートとして使用

iptables構成

●PREROUTINGチェイン
PREROUTINGチェインにて、Main Server と Honeypot への振り分けを完結させる。

Chain PREROUTING (policy ACCEPT 1532 packets, 220K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        1    52 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:ssh match-set jpnet src to:192.168.1.1:22
2        0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:smtp to:192.168.1.1:25
3        0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set jpnet src to:192.168.1.1:80
4        0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http match-set searchengines src to:192.168.1.1:80
5        1    52 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set jpnet src to:192.168.1.1:443
6       17  1004 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https match-set searchengines src to:192.168.1.1:443
7        0     0 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:submission match-set jpnet src to:192.168.1.1:587
8        1    52 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:imaps match-set jpnet src to:192.168.1.1:993
9       31  1840 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:http to:192.168.1.1:9080
10      49  2852 DNAT       tcp  --  ppp0   any     anywhere             anywhere             tcp dpt:https to:192.168.1.1:9443

・jpnet
 日本国内からのアクセスを Main Server(80 / 443)へ振り分け

・searchengines
 主要サーチエンジンのアクセスを Main Server(80 / 443)へ振り分け

・上記に該当しないWebアクセス
 Honeypot(9080 / 9443)へ振り分け

●FORWARDチェイン
Honeypotの通信制御および有効/無効の切り替えを担当。

Chain FORWARD (policy DROP 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1    13794 8169K ACCEPT     all  --  any    any     anywhere             anywhere             state RELATED,ESTABLISHED
2        0     0 DROP       tcp  --  br0    ppp0    anywhere             anywhere             tcp dpts:137:netbios-ssn
3        0     0 DROP       udp  --  br0    ppp0    anywhere             anywhere             udp dpts:netbios-ns:139
4        0     0 DROP       tcp  --  br0    ppp0    anywhere             anywhere             tcp dpt:microsoft-ds
5        0     0 DROP       udp  --  br0    ppp0    anywhere             anywhere             udp dpt:445
6        0     0 DROP       tcp  --  br0    ppp0    anywhere             anywhere             tcp dpt:sunrpc
7        0     0 DROP       udp  --  br0    ppp0    anywhere             anywhere             udp dpt:sunrpc
8      367  116K ACCEPT     all  --  br0    ppp0    192.168.1.0/24       anywhere
9       59  3448 DROP       all  --  ppp0   br0     anywhere             anywhere             match-set firehol_level3 src
10       0     0 DROP       all  --  ppp0   br0     anywhere             anywhere             match-set firehol_level2 src
11       0     0 DROP       all  --  ppp0   br0     anywhere             anywhere             match-set firehol_level1 src
12       0     0 DROP       all  --  ppp0   br0     anywhere             anywhere             match-set gcloud src
13       4   240 ACCEPT     tcp  --  ppp0   br0     anywhere             192.168.1.1          tcp dpt:9080
14      17  1004 ACCEPT     tcp  --  ppp0   br0     anywhere             192.168.1.1          tcp dpt:9443
15      20  1160 ACCEPT     all  --  ppp0   br0     anywhere             192.168.1.1

・firehol_level1~3
 FireHOL公開のブラックリストIPを遮断(Main / Honeypot 共通)

・gcloud
 スパム傾向の強い Google Cloud からのアクセスを遮断(同上)

■補足

・FORWARDチェインのルール13,14の挿入位置を9~12の前へ移動することで、Honeypotへの到達条件をより優先的に適用可能
・ハニーポットを無効化する場合は、ルール13,14をDROPへ変更することで即時切り替え可能
・単一ホスト構成のため、iptablesのルール変更のみで挙動を動的に制御できる点も利点である

この構成により、単一ホストで完結しつつ柔軟な制御が可能となり、シンプルかつ合理的な構成となった。

■副次効果(ACME運用の簡素化)

今回の構成変更により、ハニーポットへの振り分けだけでなく、証明書更新(ACME)の運用面でも副次的なメリットが得られた。
従来、Let’s Encrypt の HTTP-01 チャレンジによる証明書更新においては、ポート80 について一時的に国内限定を解除する必要があったが、本構成ではそれが不要となる。
具体的には、renewal 配下のコンフィグファイルにおいて、Certbot が生成する検証ファイルの配置先である [renewalparams] と [[webroot_map]] の webroot パスを変更するだけでよい。
すなわち、Let’s Encrypt の HTTP-01 チャレンジをハニーポット上で完結させる構成となる。

[renewalparams]
account = xxxxxxxxxxxxxxxxxxxxxxxxx
authenticator = webroot
webroot_path = /mnt/data/sky, /mnt/data/pacific
server = https://acme-v02.api.letsencrypt.org/directory
key_type = ecdsa
[[webroot_map]]
sky.0t0.jp = /mnt/data/sky
pacific.sky.0t0.jp = /mnt/data/pacific
     ↓
[renewalparams]
account = xxxxxxxxxxxxxxxxxxxxxxxxx
authenticator = webroot
webroot_path = /mnt/data/honeypot/sky, /mnt/data/honeypot/pacific  #ハニーポットのパスに変更
server = https://acme-v02.api.letsencrypt.org/directory
key_type = ecdsa
[[webroot_map]]
sky.0t0.jp = /mnt/data/honeypot/sky  #ハニーポットのパスに変更
pacific.sky.0t0.jp = /mnt/data/honeypot/pacific  #ハニーポットのパスに変更