VPSで構築する「自分専用画像生成サーバー」のセキュリティ対策とアクセス制限
最初に結論を書いておきます
SD WebUIをVPSに立てたら、セキュリティ対策だけはさぼるな。これだけは絶対。
理由はシンプルです。IPアドレスをそのままさらした状態で公開すると、世界中の誰でもアクセスしてGPUリソースをタダ乗りできます。GPU VPSは時間課金のものも多い。誰かに使い倒されて、自分に請求だけ来る、という状況は笑えない。
正直に言うと、最初に自分がSD WebUIを立てたとき「まぁ自分のIPアドレスなんて誰も知らないし大丈夫でしょ」と思っていました。でもボットはそんなの関係なく、常時ポートスキャンしています。「知られていないから安全」は通用しない。実際にBAN前のアクセスログを見たら、立ち上げてから数時間でポートスキャンの痕跡がありました。
このガイドでは、自分が実際に使っている多層防御の手順をそのまま共有します。難しそうに見えるけど、コマンドをコピペで進めるだけなので、一度やれば「ああこんなもんか」ってなります。
セキュリティリスクの全体像
まず何が怖いのかを整理しておきます。怖いものを知らずに対策だけ覚えても、どこかで手を抜きがちになるので。
| リスク | 影響 | 対策 |
|---|---|---|
| 無断アクセス・不正利用 | GPUリソース枯渇・課金 | IPホワイトリスト |
| 盗聴・通信傍受 | プロンプト・画像の流出 | HTTPS (Let’s Encrypt) |
| ブルートフォース攻撃 | 認証突破 | Basic認証 + fail2ban |
| ポートスキャン | サービス発見 | UFW + 非標準ポート |
| WebUI脆弱性悪用 | サーバー乗っ取り | 定期アップデート |
自分が特に気にしているのは「GPUリソース枯渇・課金」です。GPU VPSは月数万円かかるものも多い。正直、立ち上げが楽ならありだとは思うけど、まぁまぁ高い。だからこそ、その費用を見知らぬ誰かのために払う羽目になるのは絶対に避けたい。ここだけは妥協しないでください。
Step 1: UFWファイアウォールの設定
まず不要なポートを全部閉じます。「必要なものだけ開ける」の発想で進めてください。
# UFWを有効化(SSH接続が切れないようにSSHを先に許可)
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
# WebUIポートは最初は閉じておく(nginxで代理する)
sudo ufw deny 7860/tcp
sudo ufw deny 7865/tcp
# HTTPSのみ開放
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
WebUIのポート(7860)を直接開けないのがポイントです。外からnginxを通らずに直アクセスされる経路を最初から塞いでおく。
ここをさぼって「ポート7860を直接開放」している記事もよく見かけますが、それだとnginxで設定するBasic認証やIPホワイトリストを全部すり抜けられます。手順を省略した結果、一番守りたいところが無防備になる、という本末転倒な状態になるのでやめてください。
Step 2: nginxのインストールとリバースプロキシ設定
WebUIを直接公開せず、nginxを経由させます。ここでBasic認証とIPホワイトリストを一緒に設定するので、このステップがセキュリティの中核になります。
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
Basic認証用のパスワードファイルを作成
sudo apt install -y apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd your_username
# パスワードを入力するプロンプトが表示される
パスワードは8文字以上・英数字記号混在で設定してください。「password123」みたいなやつは論外です。「自分しか使わないから簡単でいい」という発想がそもそも危ない。
nginxの設定ファイルを作成
sudo tee /etc/nginx/sites-available/sd-webui << 'EOF'
server {
listen 80;
server_name YOUR_DOMAIN_OR_IP;
# HTTPSへリダイレクト(ドメインがある場合)
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name YOUR_DOMAIN_OR_IP;
# SSL証明書(Let's Encryptで取得後に設定)
ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
# Basic認証
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
# IPホワイトリスト(自分のIPのみ許可)
allow YOUR_HOME_IP;
allow YOUR_MOBILE_IP;
deny all;
location / {
proxy_pass http://127.0.0.1:7860;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 300;
proxy_send_timeout 300;
# WebSocket対応(WebUIに必要)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
EOF
sudo ln -s /etc/nginx/sites-available/sd-webui /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
YOUR_HOME_IP には自分の自宅回線のIPを入れます。curl ifconfig.me で確認できます。
IPホワイトリストとBasic認証を両方設定しているのがポイントで、片方だけだと片方が破られたときに終わります。二重にしておくと、どちらかが突破されても残りの層で止められる。
Step 3: HTTPS化(Let’s Encrypt)
独自ドメインがある場合は無料のSSL証明書が取れます。HTTPS化は必須です。 HTTPのままだとプロンプトも画像も通信が丸見えになります。
sudo apt install -y certbot python3-certbot-nginx
# ドメイン用の証明書を取得
sudo certbot --nginx -d YOUR_DOMAIN.com
# 証明書の自動更新を確認
sudo certbot renew --dry-run
ドメインを持っていない場合は自己署名証明書で代用できます。ブラウザに「安全でない」と表示されますが、自分しか使わないので実害はありません。
# 自己署名証明書の生成
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/sd-webui.key \
-out /etc/ssl/certs/sd-webui.crt \
-subj "/CN=YOUR_VPS_IP"
本音を言えば、長期運用するなら数百円/年の独自ドメインを取った方がいいです。.com じゃなくても .xyz とか安いやつで十分。仮に年300円だとして、GPU VPSの月額と比べたら誤差もいいところなので、ケチる意味がない。
Step 4: fail2banでブルートフォース攻撃対策
Basic認証があってもパスワードを総当たりで試してくるボットはいます。fail2banを入れると、一定回数認証に失敗したIPを自動でBANしてくれます。
sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
[sshd]
enabled = true
port = ssh
maxretry = 3
EOF
sudo systemctl restart fail2ban
sudo fail2ban-client status
maxretry = 5 は「5回失敗したらBAN」という設定です。SSHは3回に絞っています。SSH乗っ取りはGPUの不正利用より深刻なので、こちらは厳しめに。
bantime の3600秒(1時間)は短めに見えるかもしれないけど、本物の攻撃者はそんなに同じIPから続けてきません。再試行間隔を伸ばすことで実質的な攻撃コストが上がれば十分です。
Step 5: WebUI自体のセキュリティ設定
WebUIを起動するときに 127.0.0.1 にバインドします。これでnginxを経由しない直アクセスができなくなります。
# WebUI起動時のオプション(localhostのみにバインド)
python launch.py --listen 127.0.0.1 --port 7860 \
--api --api-auth username:password \
--cors-allow-origins https://YOUR_DOMAIN.com
はっきり書いておきます。--listen 0.0.0.0 で起動しているブログ記事やQiitaの解説を見かけることがありますが、あれはやめてください。全インターフェースで待ち受けることになるので、UFWでポートを閉じていても設定ミスがあった瞬間に素通しになります。「動作確認のためにとりあえず」でそのまま本運用に移行しているケースが多いので、最初から 127.0.0.1 で習慣づけてください。
セキュリティ確認チェックリスト
設定が終わったら、以下のコマンドで状態を確認してください。「設定したつもり」で穴が開いているケースはよくあります。自分は立ち上げ直後に必ずこれを一通り流しています。
# 開いているポートの確認
sudo ss -tlnp | grep LISTEN
# ファイアウォールの状態確認
sudo ufw status verbose
# fail2banのBAN状況確認
sudo fail2ban-client status nginx-http-auth
# nginx エラーログの監視
sudo tail -f /var/log/nginx/error.log
# WebUIへの不正アクセス試行を検知
sudo grep "401" /var/log/nginx/access.log | tail -20
grep "401" を眺めるのが習慣になっています。立ち上げてすぐの段階でもボットがアクセスを試みている形跡が残っていて、毎回「対策していてよかった」と思います。逆に言うと、対策していなかったら本当にやばかったということでもある。
よくある質問
まとめ:あなたの使い方で選ぶ判断テーブル
適切なセキュリティ対策を施した画像生成サーバーの構成は以下のようになります。
インターネット
↓
VPS側ファイアウォール(コントロールパネル)
↓ 443のみ通過
UFW(OS側ファイアウォール)
↓
nginx(IPホワイトリスト + Basic認証 + HTTPS)
↓
SD WebUI(127.0.0.1のみリッスン)
この多層防御で、不正アクセスのリスクは大幅に下がります。全部一度にやる必要はないので、自分の状況に合わせた優先順位の目安を下に置いておきます。
| あなたの使い方 | 最優先でやること | 次にやること | 正直な一言 |
|---|---|---|---|
| とにかく早く立ち上げたい | UFW設定 + WebUIを127.0.0.1バインド | Basic認証 + fail2ban | この2つだけでもだいぶ違う |
| 自宅固定回線のみ使う | IPホワイトリスト | HTTPS化 | 最強構成に近い。羨ましい |
| モバイルからも使いたい | VPN導入 → 固定IP経由でホワイトリスト | Basic認証強化 | VPN代は誤差。迷わず導入 |
| 独自ドメインを持っている | Let’s EncryptでHTTPS化 | VPS側ファイアウォールも二重設定 | 証明書は無料。やらない手はない |
| ドメインなし・IPのみ運用 | 自己署名証明書でもHTTPS化 | IPホワイトリスト必須 | ドメイン、年300円で取れるよ |
| GPU VPSを時間課金で使っている | IPホワイトリスト + UFW | fail2banを厳しめに設定 | 課金リスクが一番高い構成。絶対やって |
全部一度にやろうとするとしんどいので、UFWとWebUIの127.0.0.1バインドだけでも先にやっておくのがおすすめです。それだけでリスクはかなり下がります。残りは使いながら順番に足していけばいい。
これが最終回答じゃないし、完璧にしてから使い始める必要もありません。まずは動かして、セキュリティは育てていく感覚で。