How-Tos には投稿できないため、こちらに投稿します ![]()
概要
既存のリソースに WAF を追加しつつ、小規模なインストール環境でもパフォーマンスを維持することが目的です。この例では、単一の EC2 インスタンスを使用します。Discourse は Docker 上で実行されているため、ホストに NGINX をインストールし、proxy_pass を使用してトラフィックを Docker コンテナに転送できます。また、PostgreSQL には RDS を使用しています。
Discourse の設定
最初のステップとして、カスタム Discourse インストール用に app.yml ファイルを設定します。この例では、web ロールと redis ロールを実行します。DB ロールや SSL ロールは使用しません。
また、Docker コンテナで Web ポートを公開しないようにする必要があります。その理由は、ホスト上の NGINX プロキシを通じて Web を公開するためです。
app.yml ファイルの例
## これはオールインワンのスタンドアロン Discourse Docker コンテナテンプレートです
##
## このファイルを編集した後、必ず再構築してください
## /var/discourse/launcher rebuild app
##
## 編集時には非常に注意してください!
## YAML ファイルは、空白やアライメントの誤りに極めて敏感です!
## 必要に応じて http://www.yamllint.com/ でこのファイルを検証してください
templates:
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
- "templates/web.socketed.template.yml"
## Lets Encrypt (https) を追加する場合は、以下の 2 行のコメントを外してください
#- "templates/web.ssl.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
## このコンテナが公開する TCP/IP ポートはどれですか?
## Discourse を Apache や nginx などの他の Web サーバーとポートを共有したい場合は、
## https://meta.discourse.org/t/17247 を参照してください
expose:
# - "80:80" # http
# - "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## db_shared_buffers を総メモリの最大 25% に設定します。
## 検出された RAM に基づいてブートストラップによって自動的に設定されますが、上書きすることも可能です
db_shared_buffers: "768MB"
## ソートパフォーマンスを向上させることができますが、接続ごとのメモリ使用量が増加します
#db_work_mem: "40MB"
## このコンテナが使用する Git リビジョンはどれですか?(デフォルト: tests-passed)
#version: tests-passed
env:
LANG: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## 同時にサポートされる Web リクエスト数は?メモリと CPU コア数に依存します。
## 検出された CPU に基づいてブートストラップによって自動的に設定されますが、上書きすることも可能です
UNICORN_WORKERS: 2
## TODO: この Discourse インスタンスが応答するドメイン名
## 必須です。Discourse は IP アドレスのみでは動作しません。
DISCOURSE_HOSTNAME: cloudforums.net
## 上記で指定したホスト名(-h オプション)と同じホスト名でコンテナを起動したい場合は、
## 以下のコメントを外してください(デフォルトは「$hostname-$config」)
#DOCKER_USE_HOSTNAME: true
## TODO: 初期登録時に管理者および開発者として設定されるメールアドレスのリスト(カンマ区切り)
## 例: 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: 'youremail@domain.com'
## TODO: 新しいアカウントの検証や通知の送信に使用する SMTP メールサーバー
# SMTP アドレス、ユーザー名、パスワードは必須です
# 警告: SMTP パスワードに '#' 文字が含まれていると問題が発生する可能性があります!
DISCOURSE_SMTP_ADDRESS: YOUR_SMTP
DISCOURSE_SMTP_PORT: 587
DISCOURSE_SMTP_USER_NAME: YOUR_SMTP_USERNAME
DISCOURSE_SMTP_PASSWORD: YOUR_SMTP_PASSWORD
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (オプション、デフォルトは true)
## Lets Encrypt テンプレートを追加した場合は、以下のコメントを外して無料の SSL 証明書を取得してください
#LETSENCRYPT_ACCOUNT_EMAIL: me@example.com
DISCOURSE_DB_SOCKET: ''
DISCOURSE_DB_USERNAME: YOUR_USERNAME
DISCOURSE_DB_PASSWORD: YOUR_PASSWORD
DISCOURSE_DB_HOST: YOUR_HOST
## この Discourse インスタンスの HTTP または HTTPS CDN アドレス(プルするように設定)
## 詳細については https://meta.discourse.org/t/14857 を参照してください
#DISCOURSE_CDN_URL: https://discourse-cdn.example.com
## Docker コンテナはステートレスです。すべてのデータは /shared に保存されます
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## プラグインはここに追加します
## 詳細については https://meta.discourse.org/t/19157 を参照してください
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## ビルド後に実行するカスタムコマンド
run:
- exec: echo "カスタムコマンドの開始"
## 最初の登録時の 'From' メールアドレスを設定したい場合は、以下のコメントを外して変更してください
## 最初のサインアップメールを受信した後、再度コメントアウトしてください。1 回だけ実行すれば十分です
- exec: rails c "SiteSetting.enable_badge_sql = true"
- exec: echo "カスタムコマンドの終了"
Discourse インストールの開始
Discourse リポジトリのクローン
sudo -u root git clone https://github.com/discourse/discourse_docker.git /var/discours
インストール用のカスタム app.yml のコピー
以下のコマンドを実行することで、自動的にコピーできます。テスト文字列 “PASTE YOUR FULL APP.YML HERE” を、完全な app.yml に置き換えてください。
sudo -u root cat > /var/discourse/containers/app.yml <<\EOF
PASTE YOUR FULL APP.YML HERE
EOF
Discourse セットアップの実行
以下のコマンドを使用して、プロンプトなしで Discourse セットアップを開始します。
sudo -u yes "" | /var/discourse/./discourse-setup
Discourse のインストールには 10〜15 分かかります。
NGINX、WAF、および GEOIP のインストール
アップデートを実行し、前提条件をインストールします
apt update -y
apt upgrade -y
apt -y install libpcre3-dev libssl-dev unzip build-essential daemon libxml2-dev libxslt1-dev libgd-dev libgeoip-dev zlib1g-dev libpcre3
位置に基づいて GEO IP ルールを実行できるように、MindMax DB をインストールします。このデータベースを使用して、位置に基づいてトラフィックをルーティングまたはブロックできます。Geo ブロックを有効にしなくても、NGINX ログにユーザーの国が表示されるようになります。
sudo add-apt-repository -y ppa:maxmind/ppa
apt update -y
apt install -y libmaxminddb0 libmaxminddb-dev mmdb-bin
NGINX と NAXSI WAF のダウンロードと展開
注: NGINX を最新バージョンに置き換えてください
mkdir ~/nginx-waf
wget https://nginx.org/download/nginx-1.16.1.tar.gz -O ~/nginx-waf/nginx.tar.gz
tar xzf ~/nginx-waf/nginx.tar.gz -C ~/nginx-waf
wget https://github.com/nbs-system/naxsi/archive/master.zip -O ~/nginx-waf/waf.zip
unzip ~/nginx-waf/waf.zip -d ~/nginx-waf/
NGINX 用の GEO IP2 モジュールを Git クローン
apt install -y git
git clone https://github.com/leev/ngx_http_geoip2_module.git /etc/ngx_http_geoip2_module
NGINX のコンパイル
この処理を行うスクリプトを作成し、実行します
cat > ~/nginx-waf/nginx-1.16.1/install.sh <<\EOF
cd ~/nginx-waf/nginx-1.16.1/
./configure --conf-path=/etc/nginx/nginx.conf --add-module=../naxsi-master/naxsi_src/ --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --user=www-data --group=www-data --with-http_ssl_module --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module --without-http_uwsgi_module --add-dynamic-module=/etc/ngx_http_geoip2_module --without-http_scgi_module --prefix=/usr
make
make install
EOF
sh ~/nginx-waf/nginx-1.16.1/install.sh
ファイアウォールルールの作成
以下のデフォルト設定では WAF が有効になり、悪意のあるリクエストがブロックされます。WAF を学習モードで実行したい場合は、以下のルールファイルに Learning Mode を追加してください。
cp ~/nginx-waf/naxsi-master/naxsi_config/naxsi_core.rules /etc/nginx/
cat > /etc/nginx/naxsi.rules <<\EOF
SecRulesEnabled;
DeniedUrl "/RequestDenied";
## Naxsi ルールを確認
CheckRule "$SQL >= 8" BLOCK;
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 4" BLOCK;
CheckRule "$EVADE >= 4" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
EOF
NGINX 設定ファイルの作成
この設定ファイルでは、デフォルトで Geo ブロックがコメントアウトされていますが、必要に応じてコメントを外して有効にできます。
注: 最初に NGINX を SSL なしで実行する必要があります。certbot がライブドメインを検出できるようにするためです。SSL は後続のステップで取得し、新しい NGINX 設定ファイルをコピーして置き換えます
注: cloudforums.net をあなたのドメイン名に置き換えてください
cat > /etc/nginx/nginx.conf <<\EOF
#user nobody;
worker_processes 1;
load_module modules/ngx_http_geoip2_module.so;
events {
worker_connections 1024;
}
http {
include mime.types;
include /etc/nginx/naxsi_core.rules;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
geoip2 /etc/geo_ip/GeoLite2-Country.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
$geoip2_data_country_name source=$remote_addr country names en;
}
log_format main_geo '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$geoip2_data_country_code $geoip2_data_country_name';
access_log /var/log/nginx/access.log main_geo;
default_type application/octet-stream;
error_log /var/log/nginx/error.log;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name cloudforums.net;
root /;
location /.well-known/acme-challenge/ {
root /var/www;
}
location / {
return 301 https://$host$request_uri;
include /etc/nginx/naxsi.rules;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
EOF
NGINX 用 upstart スクリプトの作成
NGINX サービスを起動するためのスクリプトを作成する必要があります
cat > /etc/init.d/nginx <<\EOF
#! /bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# 利用可能な場合は nginx のデフォルト設定を含めます
if [ -f /etc/nginx ] ; then
. /etc/nginx
fi
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile \
/var/run/nginx.pid --exec $DAEMON
sleep 1 start-stop-daemon --start --quiet --pidfile \
/var/run/nginx.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
reload)
echo -n "Reloading $DESC configuration: "
start-stop-daemon --stop --signal HUP --quiet --pidfile /var/run/nginx.pid \
--exec $DAEMON
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
EOF
systemctl daemon-reload
NGINX サービスファイルの作成
cat > /lib/systemd/system/nginx.service <<\EOF
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
Geo IP 国データベースのダウンロード
mkdir /etc/geo_ip
wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
gzip -d GeoLite2-Country.mmdb.gz
mv GeoLite2-Country.mmdb /etc/geo_ip/
NGINX の有効化と起動
systemctl stop apache2
systemctl daemon-reload
systemctl enable nginx
systemctl start nginx
ドメイン用の SSL 証明書の追加
cloudforums.net をあなたのドメイン.com に置き換えるのを忘れないでください
mkdir /var/www
apt-get -y update
apt-get -y install letsencrypt
yes "n" | letsencrypt certonly --webroot --agree-tos -w /var/www -d cloudforums.net -m youremail@domain.com
SSL ルールを含む新しい NGINX ファイルの作成
先ほどダウンロードした SSL 証明書を含む新しい NGINX ファイルを作成します。
注: cloudforums.net をあなたのドメインに変更してください
cat > /etc/nginx/nginx.conf <<\EOF
#user nobody;
worker_processes 1;
load_module modules/ngx_http_geoip2_module.so;
events {
worker_connections 1024;
}
http {
include mime.types;
include /etc/nginx/naxsi_core.rules;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
geoip2 /etc/geo_ip/GeoLite2-Country.mmdb {
$geoip2_data_country_code source=$remote_addr country iso_code;
$geoip2_data_country_name source=$remote_addr country names en;
}
log_format main_geo '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$geoip2_data_country_code $geoip2_data_country_name';
#***********************************************************
# Geo ブロックを実行するにはコメントを外してください。デフォルトでは以下の設定で米国のみが許可されています
#***********************************************************
#map $geoip2_data_country_code $allowed_country {
# default no;
# US yes;
# }
access_log /var/log/nginx/access.log main_geo;
default_type application/octet-stream;
error_log /var/log/nginx/error.log;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name cloudforums.net;
root /;
location /.well-known/acme-challenge/ {
root /var/www;
}
location / {
return 301 https://$server_name$request_uri;
include /etc/nginx/naxsi.rules;
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 443 ssl; listen [::]:443 ssl;
server_name cloudforums.net;
ssl on;
ssl_certificate /etc/letsencrypt/live/cloudforums.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cloudforums.net/privkey.pem;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=63072000;";
ssl_stapling on;
ssl_stapling_verify on;
client_max_body_size 0;
location / {
proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
}
}
# HTTPS サーバー
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
EOF
NGINX の再起動
systemctl restart nginx
これで、素晴らしいオープンソース WAF が完成しました!![]()
宣伝
このガイドを楽しんでいただけた場合は、cloudforums.net への参加をお忘れなく。ぜひ皆様にお越しいただきたいです。私たちは物を売ったり広告を出したりしていません。良い IT 投稿を探しているだけです ![]()
