UFWもDiscourseを制限しますか?

Discourse はどのように UFW をバイパスできるのでしょうか?ポート 22 のみを有効にし、他のすべてのポートは閉じたはずです。しかし、フォーラムは機能していました。どうして可能なのでしょうか?

DigitalOcean のドロップレットですが、それは関係ないはずです。また、ワンクリックインストールではなく、公式の方法です。

これは純粋なサポート質問ではありませんが、ここには「初心者による愚かな基本的な質問」というカテゴリがありません :wink:

「いいね!」 7

ufw status verbose を実行すると、sshd のみ表示されるということですか?

「いいね!」 1

はい、その通りです。そしてUFWが有効になっていました。

「いいね!」 1

ufw status verbose を実行したときにデフォルトで表示されたのは何ですか?

あなたが望んでいると思われるものについては、次のように表示されるはずです。
デフォルト: deny (着信), allow (発信), disabled (ルーティング済み)

あなたが説明している動作については、次のように表示されるはずです。
デフォルト: allow (着信), allow (発信), disabled (ルーティング済み)

「いいね!」 1

インコグニートウィンドウまたは別のブラウザでフォーラムを開いてみましたか?キャッシュされたバージョンが表示されるのに簡単に騙されることがあります。私自身も騙されたことがあり、ステージングサイトが全く動作していないのに、別の開発者に「ステージングサイトは問題ない」と言われたことがあります。

「いいね!」 1
22/tcp (OpenSSH)           ALLOW IN    Anywhere

と、あるべき通りでした。私が常に実行する2つのことは、OpenSSHを許可し、UFWを有効にすることです。

Nginxをインストールする場合のように、必要に応じてポートを開きます。しかし、そのVPSはDiscourse専用だったので、それ以外は何もせず、UFWを完全に忘れていました。

それはありえません。そのフォーラムは数週間生きていました。

Nginx/VarnishをそのVPSに接続して別のポートを開く必要があったときに、この状況に気づきました。開いていたのはポート22だけでした。

編集:
メールを送信するにはどうすればよいですか?ポート587も開いていませんでした😳

これは本当に奇妙です。

「いいね!」 1

デフォルトが拒否に設定されているのかどうか、明確ではありません。「デフォルト」行について具体的に質問している理由は、デフォルトを許可に設定し、特定のポートを許可するように設定することも可能ですが、後者はその構成では何も変更されないためです。

もし他の誰かが Discourse を設定した場合、その人がデフォルトを許可ではなく、HTTP/HTTPS ポートを許可するように変更した可能性はありますか?

これはどこかの SMTP サーバーへの接続だと推測します。Discourse サーバーがポート 587 を使用してその SMTP サーバーに接続しているということです。デフォルトではすべてのポートへのアウトバウンド接続が許可されているため、送信ポリシーを明示的に変更しない限り、UFW はメール送信の妨げにはなりません。

「いいね!」 4

私のミスです :man_facepalming:

Default: deny (incoming), allow (outgoing), deny (routed)

いいえ。しかし、allow (outgoing) は何かを送信することを許可しますか?もしそうなら、「初心者による愚かな基本的な質問」というカテゴリはありません」に戻り、新しいことを学びました。

編集:

まだ迷っていますが、deny (incoming はどうですか?

「いいね!」 2

これを見つけました。

「いいね!」 2

短い答えは、Discourse はファイアウォール ルールをバイパスできないということです。OS に関する愚かな質問をする場所は、Stack Exchange のような場所です。(失礼だと思わないでください。そのような答えはそこにあります。初期のリリースから Linux を実行してきましたが、今でもそのような場所で愚かな質問をしています。まだあります!)

「いいね!」 3

その場所は知っています :wink: 信号対雑音比が非常に高すぎます。まあ、それは不公平な特徴付けでしたが、そこから関連性の高いものを見つけるのは本当に難しいという意味でした。それは非常に大規模です。

「いいね!」 2

これは実際には非常に良い質問であり、他の誰もまだ尋ねていないことに驚いています。答えは複雑ですが、これまでのところ、このトピックに関する回答は、質問に答えることなく、残念ながら軽視するようなトーンでした。

Discourseがufwをバイパスしているわけではなく、dockerがufwをバイパスして、ufwが存在してもdockerコンテナの公開ポートが機能するようにルールを追加しているのです。

何が起こっているのか?

コンテナ宛ての着信パケットは、予想されるかもしれないINPUTテーブルではなく、FORWARDテーブルにヒットします。

dockerインストール前

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-before-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-after-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-reject-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-track-forward  all  --  any    any     anywhere             anywhere

dockerインストール後

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    8   416 DOCKER-USER  all  --  any    any     anywhere             anywhere            
    8   416 DOCKER-ISOLATION-STAGE-1  all  --  any    any     anywhere             anywhere            
    0     0 ACCEPT     all  --  any    docker0  anywhere             anywhere             ctstate RELATED,ESTABLISHED
    4   256 DOCKER     all  --  any    docker0  anywhere             anywhere            
    4   160 ACCEPT     all  --  docker0 !docker0  anywhere             anywhere            
    0     0 ACCEPT     all  --  docker0 docker0  anywhere             anywhere            
    0     0 ufw-before-logging-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-before-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-after-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-after-logging-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-reject-forward  all  --  any    any     anywhere             anywhere            
    0     0 ufw-track-forward  all  --  any    any     anywhere             anywhere

パケットがforwardテーブルにヒットする理由は、dockerがnatテーブルに追加するルールによるものです。

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  210 12734 DOCKER     all  --  any    any     anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 any     anywhere             anywhere            
    0     0 DNAT       tcp  --  !docker0 any     anywhere             anywhere             tcp dpt:https to:172.17.0.2:443
  107  6848 DNAT       tcp  --  !docker0 any     anywhere             anywhere             tcp dpt:http to:172.17.0.2:80

nat/PREROUTINGは、パケットをINPUTまたはFORWARDのどちらで処理するかを決定する前に処理されます。

最終的に問題となるのは、システム上でファイアウォールルールを変更する2つのサービスがあることです。ufwはこれらを認識していないため、自分が設定したことしか報告できません。

解決策

これに対する解決策は、docker宛てのトラフィックもufwチェーンを通過するようにファイアウォールを再設定することです。

私は、ufwを有効にする前に、彼らの作業をわずかに適応させたものを使用しています。

# https://github.com/chaifeng/ufw-docker から盗用 - 合理的に見える
# forwardをufw-user-inputに追加すると、明示的に開いたポートに転送された接続が
# 可能になります
cat <<EOUFW >> /etc/ufw/after.rules
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-user-input - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16

-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN

-A DOCKER-USER -j ufw-user-forward
-A DOCKER-USER -j ufw-user-input

-A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j DROP -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
-A DOCKER-USER -j DROP -p udp -m udp --dport 0:32767 -d 192.168.0.0/16

-A DOCKER-USER -j RETURN
COMMIT
# END UFW AND DOCKER
EOUFW
「いいね!」 20

ありがとうございます。完全な説明でした。

「いいね!」 4

ようこそ、それが私のやり方です :smiley:

「いいね!」 6

このトピックは解決しましたが、私のセットアップに関する1つのマイナーな問題が明らかになりました。将来、同様のものを検索する人がいれば説明します。

Nginxが私のすべてのサイト(たくさんのオフ、英語は非常に奇妙な言語です ;))のSSLとその他の処理を担当するVPSが1つありました。NginxはVarnishにリクエストを送信します。Discourseにとっては無用なリバースプロキシですが、いくつかのフィルタリングを行います。Varnishは、Discourseが存在する別のVPSにポート83を使用してリクエストを送信します。両方のVPSは同じポートをリッスンしており、両方のIPのみが許可されています。今まで、私は完全に満足していました。

ポート443 curl -I https://forum.example.tld:443 を使用した場合に何が起こるかを試しました。Discourse側でまだ有効なSSL証明書を持っていたため、うまく機能しました(数週間前にこの変更を行いました)。

@supermathie の回答は、これがなぜ起こるのか、そしてそれを修正する方法を説明しています。もちろん、それによるセキュリティ上の問題は一切ありませんが、非常に迷惑です😝

「いいね!」 2

すごい。それはクレイジースタッフですね!ありがとうございます。

おそらく、Discourseをインストールして、それが機能しないようにしたい人がほとんどいないため、質問されないのでしょう。Dockerが、ファイアウォールを設定したにもかかわらず機能させてしまうと、ほとんどの人は文句を言いません。:wink:

非常に興味深い問題ですが、少し難解であり、Discourseの問題ではなく、Dockerの癖です。質問は「ファイアウォールを設定してDiscourseを機能しないようにするにはどうすればよいか?」という問題に集約されます。そのプリルーティングの件を覚えておこうと思います。

もし答えを知っていたら、軽視するような口調にはならなかったでしょう!:wink: 今回はこれで助かりました!

「いいね!」 6

軽視するつもりは全くなく、むしろトラブルシューティングを試みていましたが、明らかにDockerが何をしているのかを知らない状態でした。非常に役立つ情報です、回答ありがとうございます!

もしOPまたは他の誰かが変更できるなら、マークされたソリューションを変更する価値があるかもしれません。

これはDockerの問題ですが、これに起因するDiscourseの仮想的なシナリオがいくつか考えられます。例えば、外部からアクセス可能なオフィスサーバーがあるが、Discourseをオフィス内からのみアクセスできるようにUFWを設定したい場合があります。Dockerの追加機能は、そのセットアップを妨げるでしょう。

ただし、その特定のシナリオでは、ハードウェア/ハイパーバイザーファイアウォールで設定し、ホスト上のUFWではなく、そちらを使用するでしょう。

「いいね!」 5

同じgitリポジトリにたどり着きました。ufw/dockerの問題を調べていたのですが、このトピックのことを思い出しました。

具体的に何を変更しましたか(追加された行はわかりますが、それが何を意味するのか?)、そしてこれらの変更はDiscourse専用ですか?

リポジトリのデフォルトコードを使用したところ、ufwの問題はその後修正されたようです。

編集:編集されたコードを使用すると、最初にufw reloadを実行したときに次のエラーが発生します。

エラー:ロギングルールをロードできませんでした

「いいね!」 1

しばらくして自分で解決し、Discourse のインストール用にこの bash スクリプトを作成しました。

ファイアウォールをリセットし、ufw-docker-util (after.rules を編集します) をインストールしてから、ポート 443 と 80 を許可リストに追加します。これで完了です。

また、ロックアウトされないように、ポート 22 を任意の IP から許可します。すべてが機能した後、ポート 22 を再度保護します。

編集: スクリプトは機能しますが、使用後に Discourse を再構築すると失敗します: fatal: unable to access 'https://github.com/discourse/discourse.git/': Could not resolve host: github.com - このため、これを解決する方法がわからない限り、スクリプトを使用しないでください。

編集 2: Ubuntu では機能しますが、CentOS では機能しません!

「いいね!」 3

以前bashスクリプトを実行した際に、すべてのディレクトリの所有者をwww-data:www-dataに変更しました。そのため、このような作業は私の生活を少し楽にしてくれます :wink:

しかし、一般的にはDockerがUFW/iptablesに完全に追従することを望みます。なぜなら、私はiptables経由でGeoIPブロッキングを使用しているからです(ええ、わかっています — UFWはiptablesのミニマリストUIにすぎません)。

もちろん、私たちはもうDiscourseにはいませんが、ここではコーダーとエンドユーザーが常に互いをよく理解できない理由を見ることができます。コーダーは世界を論理的なブロック、if/then/elseの構築として見ていますが、エンドユーザーはそれを完全なコンテキストとして見ています。つまり — Discourseを使用しているため、たとえDocker内で動作していても、私の視点からは、私のルールに従わないのはDiscourseなのです :rofl:

これは#praiseに送られるべきですが、数週間前にフォーラムのURLを変更しました。そして、世界のすべてのスクリプトキディと役に立たないSEOボットが訪問するようになりました。DigitalOceanの2GB/1vCPU VPSで、1時間あたり3000の異なるユーザーエージェントを取得しましたが、Discourseはまったく気にしませんでした。そのようなDDoSのようなラッシュの後、WordPressのインストールは遅くなるかダウンするでしょう。

ですから、Discourse(まあ、Docker)にFail2banや私のルールによる禁止に従うことを強制する必要はありませんが、それらのボットは非常に嫌いです。

「いいね!」 3