paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

apache guacamoleで自宅サーバにアクセスしたい haproxyの防御設定を行う編

Internetから自宅アクセス用のリバースプロキシを構築したのですがInternetに晒しているので攻撃が怖いところです。

自分以外にもアクセスする人いるのかなと思ってアクセスログ見たらやっぱり来てますね。

masashi@debian-s-1vcpu-512mb-10gb-sgp1-01:~$ sudo grep -P ' \d{3} ' /var/log/haproxy-traffic.log \
  | awk 'split($4, IP, ":") {print IP[1]" "$9" "$16" "$17}' \
  | sort | uniq -c | grep -v guacamole | sort -rn | head
     11 45.190.160.59 404 "GET /admin/assets/js/views/login.js
      3 92.249.48.232 404 "GET /index.asp
      3 168.253.90.155 404 "GET /admin/assets/js/views/login.js
      3 104.248.134.97 400 "<BADREQ>" 
      2 83.97.73.245 404 "GET /actuator/gateway/routes
      2 83.97.73.245 404 "GET /?XDEBUG_SESSION_START=phpstorm
      2 8.209.96.179 404 "POST /resolve
      2 8.209.96.179 404 "POST /query
      2 8.209.96.179 404 "POST /dns-query
      2 8.209.96.179 404 "POST /

フレームワークのデフォルトパス的なやつをサーチされてる感じですね。
やはりインターネットは危険だ。
URIの本対策は後にしてとりあえずBot系のアクセスを封じます。

Firewall

iptables使っとくかと思いましたがVPSの機能を使うほうが簡単なのでこっちにします。

日本のIPからのSSHHTTPSだけ許可。
詳細は割愛しますがwordpressとhaproxyに当てました。(やってなかったのかよ)

オンプレ系のFWアプライアンスはよく触ってきましたが、最近AWS周りも触る機会があってクラウド基盤系のアクセス制御も慣れてきました。

公式対策

公式ドキュメントにBot protectionの記事があるのでこちらを参考にします。

www.haproxy.com

stick-tableという機能を使って閾値を監視してアクセス可否を設定します。
stick-tableはsticky-session等の保持に使うほか、いろいろな値を格納できるようです。

haprocx.conf

confには以下のように記載。

stick-tableに送信元IPとIP&urlを格納。 gpc0_rateが30秒間に15アクセス以上来たら拒否となります。 gpc0というのはHostヘッダのカウンタのようです。

# protection
backend per_ip_and_url_rates
    stick-table type binary len 8 size 1m expire 24h store http_req_rate(24h)

backend per_ip_rates
    stick-table type ip size 1m expire 24h store gpc0,gpc0_rate(30s)


frontend http-in
    bind *:443 ssl crt /etc/ssl/for_internet_gateway.pem
    http-request track-sc0 src table per_ip_rates
    http-request track-sc1 url32+src table per_ip_and_url_rates unless { path_end .css .js .png .jpeg .gif }

    acl exceeds_limit sc_gpc0_rate(0) gt 15
    http-request set-var(txn.acl_trigger) str("Bot_protection") if exceeds_limit
    http-request sc-inc-gpc0(0) if { sc_http_req_rate(1) eq 1 } !exceeds_limit
    http-request deny if exceeds_limit

    default_backend to_homelab

stick-table情報

socket経由で確認できる設定を追加した後サービス再起動。

global
    #log /dev/log  local0
    #log /dev/log  local1 notice
    log 127.0.0.1:514  local0 # 追加
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats socket ipv4@127.0.0.1:9999 level admin # 追加
    stats socket /var/run/hapee-lb.sock mode 666 level admin # 追加
    stats timeout 2m # 追加

しばらくおいて中身を見てみます。

IPレート

来てます来てます。

masashi@debian-s-1vcpu-512mb-10gb-sgp1-01:~$ echo "show table per_ip_rates" | socat stdio /var/run/hapee-lb.sock
# table: per_ip_rates, type: ip, size:1048576, used:8
0x55ea12d992c0: key=45.84.89.2 use=0 exp=80011991 gpc0=1 gpc0_rate(30000)=0
0x55ea12da8860: key=52.160.33.133 use=0 exp=81133074 gpc0=1 gpc0_rate(30000)=0
0x55ea12da8010: key=68.183.137.128 use=0 exp=78423986 gpc0=1 gpc0_rate(30000)=0
0x55ea12da6830: key=159.65.53.102 use=0 exp=80195062 gpc0=1 gpc0_rate(30000)=0
0x55ea12d97580: key=168.253.90.155 use=0 exp=81799354 gpc0=0 gpc0_rate(30000)=0
0x55ea12da66d0: key=178.215.236.240 use=0 exp=84416958 gpc0=1 gpc0_rate(30000)=0
0x55ea12d9b320: key=185.180.140.5 use=0 exp=85146195 gpc0=1 gpc0_rate(30000)=0

IP, urlレート

こちらも上記のIPに基づいて出よくされるようですが、よくわかりません。
普通にセッション情報保持として扱っている感じでしょうか。

masashi@debian-s-1vcpu-512mb-10gb-sgp1-01:~$ echo "show table per_ip_and_url_rates" | socat stdio /var/run/hapee-lb.sock
# table: per_ip_and_url_rates, type: binary, size:1048576, used:8
0x55ea12d98590: key=3A28E806B9B48C05 use=0 exp=85137304 http_req_rate(86400000)=1
0x55ea12d9ee60: key=4C58B18A7653BB53 use=0 exp=79513571 http_req_rate(86400000)=1
0x55ea12da8670: key=623C294434A02185 use=0 exp=81124183 http_req_rate(86400000)=1
0x55ea12d97360: key=6C5CDE33B2D7ECF0 use=0 exp=84408067 http_req_rate(86400000)=1
0x55ea12da7d80: key=9C1983EE44B78980 use=0 exp=78415095 http_req_rate(86400000)=1
0x55ea12d96ed0: key=9C1983EE9F413566 use=0 exp=80186171 http_req_rate(86400000)=1
0x55ea12d9c0c0: key=A84BD6697653BB53 use=0 exp=79534297 http_req_rate(86400000)=1

Deny log

効いているかどうかログに出したいところです。

ここを参考に log-formatを設定。

carlo.cloud

masashi@debian-s-1vcpu-512mb-10gb-sgp1-01:~$ sudo grep ACL /var/log/haproxy-traffic.log | tail -5
2024-10-12T05:52:54+09:00 localhost haproxy[81188]: 8.209.101.194:51432 [12/Oct/2024:05:52:34.144] http-in~ to_homelab/homelab 0/0/-1/-1/20008 503 216 - - sC-- 1/1/0/0/3 0/0 "GET / HTTP/1.1" ACL-Triggered:- 
2024-10-12T05:55:11+09:00 localhost haproxy[81188]: 4.246.246.216:57134 [12/Oct/2024:05:54:51.914] http-in~ to_homelab/homelab 0/0/-1/-1/20005 503 216 - - sC-- 1/1/0/0/3 0/0 "GET /owa/auth/logon.aspx HTTP/1.1" ACL-Triggered:- 
2024-10-12T07:07:24+09:00 localhost haproxy[81188]: 40.118.212.131:38764 [12/Oct/2024:07:07:04.170] http-in~ to_homelab/homelab 0/0/-1/-1/20007 503 216 - - sC-- 1/1/0/0/3 0/0 "GET / HTTP/1.1" ACL-Triggered:- 
2024-10-12T07:26:30+09:00 localhost haproxy[81188]: 213.32.39.37:47853 [12/Oct/2024:07:26:10.543] http-in~ to_homelab/homelab 0/0/-1/-1/20005 503 216 - - sC-- 1/1/0/0/3 0/0 "GET / HTTP/1.1" ACL-Triggered:- 
2024-10-12T08:36:17+09:00 localhost haproxy[81188]: 87.120.115.119:37044 [12/Oct/2024:08:35:57.917] http-in~ to_homelab/homelab 0/0/-1/-1/20007 503 216 - - sC-- 1/1/0/0/3 0/0 "GET /.env HTTP/1.1" ACL-Triggered:- 

末尾に出てるがACLの文字列が出てないですね。 というかALCじゃなくてDenyの方を出さないと意味ないですね。まだ閾値にはなるほど来てないのかな? ちょっとわからないので継続調査です。

まとめ

セキュリティ対策もちょっとしてやっとInternet向けサーバっぽくなりました。
仕事では別チームがやったりしてガッツリ関われないのですが、いざ自分でやると難しいもんですね。
しかしITの世界で働くものとしてはInternet周り、HTTP(S)の仕様やセキュリティは抑えないとですね。
もちろんいろんな用語や攻撃は知ってますが自分で対策を実装する意味で。