web-dev-qa-db-ja.com

開いているPostgreSQLポートを保護する方法

これが状況です。 TCPポート5432を利用できるようにする必要があります。ここでは、顧客がPostgreSQLデータベースにアクセスできます。

明らかな理由により、「最後の手段」としてのみ、「いいえ」とは言えません。

最大のトラブルは何ですか?インフラストラクチャをどのように防御できますか?

とにかく、なぜすべきではないそれは世界に開かれているのですか?おそらく、それは20年前のメンテナンスされていないFTPサーバーよりも安全だと思います。

追伸VPNには問題があります。いくつかの暗号化たぶん(私が彼に機能するのJDBC接続URLを提供できる場合)。

29
user239237

SSLを要求し、SELinuxをオンのままにし、ログを監視し、現在のPostgreSQLバージョンを使用します

サーバ側

SSLが必要

postgresql.confssl=onを設定し、キーファイルと証明書ファイルが適切にインストールされていることを確認します(postgresql.confのドキュメントとコメントを参照)。

クライアントで特別な設定をせずにクライアントから信頼されるようにするには、CAから証明書を購入する必要がある場合があります。

pg_hba.confでは、次のように使用します。

hostssl theuser thedatabase 1.2.3.4/32 md5

...ユーザーまたはデータベース、あるいはその両方の「すべて」を使用している可能性があり、より広いソースIPアドレスフィルターを使用している可能性があります。

ログインできるユーザーを制限し、リモートスーパーユーザーのログインを拒否する

可能であれば、ユーザーに「すべて」を許可しないでください。スーパーユーザーのログインをリモートで許可する必要がない場合は、許可しないでください。

ユーザーの権利を制限する

ログインできるユーザーの権限を制限します。それらにCREATEDBまたはCREATEUSER権限を与えないでください。

すべてのデータベースでREVOKECONNECTからのPUBLIC権限を付与し、そのデータベースにアクセスできるはずのユーザー/ロールのみに付与します。 (ユーザーをロールにグループ化し、個々のユーザーに直接ではなく、ロールに権限を与えます)。

リモートアクセスを持つユーザーは、必要なDBにのみ接続でき、実際に必要なスキーマ、テーブル、列への権限しか持たないことを確認してください。これはローカルユーザーにとっても良い習慣であり、賢明なセキュリティです。

クライアントのセットアップ

PgJDBCでパラメーターssl=true を渡します:

JDBCドライバーにSSL接続を試行して確立するように指示するには、接続URLパラメーターssl = trueを追加する必要があります。

...サーバー証明書をクライアントのトラストストアにインストールするか、ユーザーが証明書をインストールする必要がない場合は、Javaの組み込みトラストストアのいずれかのCAによって信頼されているサーバー証明書を使用します。

継続的な行動

ここでPostgreSQLを最新の状態に保つようにしてください。 PostgreSQLには認証前のセキュリティホールが2、3しかありませんでしたが、それはゼロを超えているため、最新の状態にしてください。とにかく、バグ修正はいいものです。

アクセスする必要がないことがわかっている大きなネットブロック/リージョンがある場合は、ファイアウォールを前面に追加します。

接続と切断をログに記録します(postgresql.confを参照)。可能であれば、クエリをログに記録します。可能であれば、侵入検知システムまたはfail2banなどを前面で実行します。 postgresでのfail2banには、便利なハウツー here があります

ログファイルを監視します。

ボーナスパラノイア

考える追加の手順...

クライアント証明書を要求する

必要に応じて、pg_hba.confを使用して、サーバーが信頼するX.509クライアント証明書をクライアントに提示するよう要求することもできます。サーバー証明書と同じCAを使用する必要はありません。これは、自家製のopenssl CAを使用して行うことができます。 JDBCユーザーは、クライアント証明書をJava Keystore with keytoolにインポートし、いくつかのJSSEシステムプロパティを設定して、Javaキーストアなので、完全に透過的ではありません。

インスタンスを隔離する

本当に偏執的になりたい場合は、クライアントのインスタンスを別のコンテナ/ VMで実行するか、少なくとも異なるユーザーアカウントで、必要なデータベースのみを使用して実行します。

そうすれば、PostgreSQLインスタンスが危険にさらされても、それ以上は取得できません。

SELinuxを使用する

私はこれを言う必要はありませんが...

RHEL 6または7のようなSELinuxサポートを備えたマシンを実行し、SELinuxをオフにしたり、許容モードに設定したりしないでください。強制モードのままにしておきます。

デフォルト以外のポートを使用する

のみによるセキュリティあいまいさは愚かさです。賢明なことを一度行ったら、少しあいまいなセキュリティを使用しても、おそらく害はありません。

デフォルト以外のポートでPgを実行して、自動化された攻撃者の生活を少し難しくします。

プロキシを前に置く

また、PostgreSQLの前でPgBouncerまたはPgPool-IIを実行して、接続プールおよびプロキシとして機能させることもできます。これにより、実際のデータベースホストではなく、プロキシにSSLを処理させることができます。プロキシは別のVMまたはマシン上に置くことができます。

クライアントアプリに既に組み込みのプールがない限り、接続プーリングプロキシの使用は、とにかくPostgreSQLで一般的には良い考えです。ほとんどのJavaアプリケーションサーバー、Railsなどには、組み込みのプールがあります。それでも、サーバー側のプールプロキシは無害です。

42
Craig Ringer

クレイグの印象的な行動計画の簡単な拡張:

おそらく、ユーザーは比較的少数のネットワークプロバイダー(たとえば、移動中のモバイルネットワークプロバイダー、自宅からのケーブルネットワーク、職場からの職場の発信IP)のみを使用している可能性があります。

ほとんどのネットワークプロバイダーには多くのIPがありますが、実際には多くのサブネットはありません。したがって、顧客が使用するネットワークセグメントへのpostgresqlアクセスを制限するiptablesフィルターを指定できます。これにより、ランダムに選択されたトラブルソースの攻撃の可能性が大幅に減少しました。

簡単なサポートシナリオ:

  1. あなたの顧客はあなたに電話します"ログインできません"
  2. tcpdump -i eth0 -p tcp port 5432コマンド、どこから来たのか。
  3. とともに whois 1.2.3.4このIPで使用されるIPアドレスを取得できます。たとえば、1.2.3.0/24
  4. iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 5432 -j ACCEPT(または類似したもの)は、彼の新しいサブネットとのtcp接続を許可します。

uifという非常に優れたPerlスクリプトがあり、永続的で直感的な宣言可能なiptablesルールセットを提供できます。 (「uif iptables」のGoogle)。

上記のHOWTOに基づくPostgreSQLの非常にシンプルなFail2ban構成を次に示しますが、実際にUbuntuパッケージで動作するように微調整されており、別のエラー条件をキャッチし、さまざまなデバッグメッセージをスキップして、より速くしています。

/etc/fail2ban/filter.d/local-postgresql.conf

[Definition]

failregex = <Host>\(\d+\) FATAL:  password authentication failed for .+$
            <Host>\(\d+\) FATAL:  no pg_hba.conf entry for Host .+$

ignoreregex = duration:

/etc/fail2ban/jail.d/local-postgresql.conf

[local-postgresql]
enabled  = true
filter   = local-postgresql
action   = iptables[name=PostgreSQL, port=5432, protocol=tcp]
           sendmail-whois[name=PostgreSQL, dest=root@localhost]
logpath  = /var/log/postgresql/postgresql-9.3-main.log
maxretry = 3
1
Josip Rodin

Fail2banは強力なツールですが、フィルターがそのまま機能するとは限りません。 failregexツール を使用してフィルターをテストし、引用符をエスケープすることを忘れないでください(つまり、「admin」は「admin」になります)。例として、私の/etc/log/postgresql/postgresql-9.3-main.logから次のフィルターfailregex行をテストしても、うまくいきませんでした。

fail2ban-regex '2016-09-20 14:30:09 PDT FATAL:  password authentication failed for user "admin"' '<Host>\(\d+\) FATAL:  password authentication failed for .+$'

上記は私に与えました

Failregex:合計0

Failregexを更新して、ログ形式に一致させる必要がありました。

fail2ban-regex '2016-09-20 14:30:09 PDT FATAL:  password authentication failed for user "admin"' 'FATAL:  password authentication failed for user \"<Host>\"'

これは私に肯定的な結果を与えました。

Failregex:合計1

Fail2ban-regexテストは、ログファイル全体に実装することもできます。

fail2ban-regex /var/log/postgresql/postgresql-9.3-main.log /etc/fail2ban/filter.d/postgresql.local

上記により、更新されたfailregexで次の肯定的な結果が得られました。

Failregex:合計169

1
metersales