前書き
サーバーが最近立ち上げられたばかりで、トラフィックがほとんどないか、見過ごされることになるハッカーにとって価値があると思われるものを何も提供していないため、考えがちです。 ただし、多くのエクスプロイトは自動化されており、構成の一般的なエラーを探すように特別に設計されています。 これらのプログラムは、コンテンツの性質に関係なく、ネットワークをスキャンしてサーバーを検出します。
リモート接続を許可することは、PostgreSQLデータベースの悪用につながる可能性がある、一般的で修正が容易な状況の1つです。 これは、特定の構成により、これらのプログラムがサーバーを簡単に検出できるようになるために発生します。
このチュートリアルでは、リモート接続を許可することによって生じる特定のリスクを軽減する方法を示します。 これは重要な最初のステップですが、サーバーは他の方法で危険にさらされる可能性があるため、Additional Security Considerationsで概説されているように、データを保護するための追加の対策を講じることもお勧めします。
バックグラウンド
軽減している特定のリスクを理解するために、サーバーをストアとして想像してください。 サーバーがポートをまったくリッスンしている場合は、ネオンの「オープン」サインをオンにするようなものです。 これにより、自動化されたスクリプトがサーバーを見つけることができるネットワーク上でサーバー自体が見えるようになります。
各ポートは、ドアや窓のような店に入る方法と考えることができます。 これらの入り口は、リッスンしているソフトウェアの状態に応じて、開いたり、閉じたり、ロックされたり、壊れたりする場合がありますが、パブリックインターフェイスでリッスンすると、内部に入ろうとするスクリプトが試行を開始できます。 たとえば、スクリプトは、変更されていない可能性がある場合にデフォルトのパスワードでログインを試みるように構成されている場合があります。 パッチが適用されていない場合、リスニングデーモンの既知の悪用を試みる可能性があります。 スクリプトが試行するものが何であれ、弱点を見つけてそれを悪用できる場合、侵入者は内部にいて、サーバーを侵害するという深刻なビジネスに取りかかることができます。
postgresql
のようなデーモンをローカルでリッスンするように制限すると、外部への特定のドアが存在しないようになります。 少なくともPostgresに関しては、試すべき次のステップはありません。 ファイアウォールとVPNも同様の方法で保護します。 このチュートリアルでは、一般公開されている出入り口としてのPostgreSQLの削除に焦点を当てます。 デーモン自体または送信または保存されるデータを保護するには、Additional Security Considerationsを参照してください。
前提条件
このチュートリアルでは、two Ubuntu installationsを使用します。1つはデータベースホスト用で、もう1つはホストにリモート接続するクライアントとして使用します。 それぞれにsudo
ユーザーがあり、ファイアウォールが有効になっている必要があります。 ガイドのInitial Server Setup with Ubuntu 16.04がこれを支援します。
One Ubuntu 16.04 PostgreSQL Database Host:
PostgreSQLをまだインストールしていない場合は、次のコマンドを使用してインストールできます。
sudo apt-get update
sudo apt-get install postgresql postgresql-contrib
One Ubuntu 16.04 Client Machine:
リモート接続を許可することを実証およびテストするために、PostgreSQLクライアントpsql
を使用します。 それをインストールするには、次のコマンドを使用します。
sudo apt-get update
sudo apt-get install postgresql-client
これらの前提条件が整ったら、準備ができています。
デフォルト設定について
PostgreSQLがUbuntuパッケージからインストールされると、デフォルトでローカルホストでのリッスンに制限されます。 このデフォルトは、postgresql.conf
ファイルのlisten_addresses
をオーバーライドすることで変更できますが、デフォルトでは、サーバーがパブリックインターフェイスで自動的にリッスンすることはできません。
さらに、pg_hba.conf
ファイルは、Unix / Linuxドメインソケットとサーバーのローカルループバックアドレスからの接続のみを許可するため、外部ホストからの接続を受け入れません。
交換する
# Put your actual configuration here
# ----------------------------------
#
# If you want to allow non-local connections, you need to add more
# "host" records. In that case you will also need to make PostgreSQL
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
# DO NOT DISABLE!
# If you change this first entry you will need to make sure that the
# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local all postgres peer
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 md5
# IPv6 local connections:
host all all ::1/128 md5
これらのデフォルトは、パブリックインターフェイスをリッスンしないという目的を満たしています。 それらをそのままにしてファイアウォールを維持すれば、完了です! Additional Security Considerationsに直接進んで、転送中のデータを保護する方法を学ぶことができます。
リモートホストから接続する必要がある場合は、デフォルトをオーバーライドする方法と、次のセクションでサーバーを保護するためにすぐに実行できる手順について説明します。
リモート接続の構成
実稼働環境で、機密データの操作を開始する前に、理想的には、PostgreSQLトラフィックを転送中にSSLで暗号化し、外部ファイアウォールの背後で保護するか、仮想プライベートネットワーク(VPN)で保護します。 そのために、データベースサーバーでファイアウォールを有効にし、それを必要とするホストへのアクセスを制限する、それほど複雑ではない手順を踏むことができます。
[[ステップ-1 -—-ユーザーとデータベースの追加]] ==ステップ1—ユーザーとデータベースの追加
まず、作業をテストできるユーザーとデータベースを追加します。 そのために、PostgreSQLクライアントpsql
を使用して、管理ユーザーpostgres
として接続します。 -i
オプションをsudo
に渡すことで、postgresユーザーのログインシェルを実行します。これにより、.profile
またはその他のログイン固有のリソースからオプションが確実に読み込まれます。 -u
はpostgresユーザーの種です:
sudo -i -u postgres psql
次に、パスワードを持つユーザーを作成します。 以下で強調表示されている例の代わりに、安全なパスワードを使用してください。
CREATE USER sammy WITH PASSWORD 'password';
ユーザーが正常に作成されると、次の出力が表示されます。
OutputCREATE ROLE
[.note]#Note: PostgreSQL 8.1以降、ROLESとUSERSは同義語です。 慣例により、パスワードを持つロールは引き続きUSERと呼ばれ、持たないロールはROLEと呼ばれるため、USERが表示されると予想される出力にROLEが表示される場合があります。
#
次に、データベースを作成し、新しいユーザーにフルアクセスを許可します。 ベストプラクティスでは、ユーザーに必要なアクセスのみを許可し、必要なリソースのみに許可することを推奨しています。そのため、ユースケースによっては、ユーザーのアクセスをさらに制限することが適切な場合があります。 権限の詳細については、ガイドHow To Use Roles and Manage Grant Permissions in PostgreSQL on a VPSを参照してください。
CREATE DATABASE sammydb OWNER sammy;
データベースが正常に作成されると、確認が表示されます。
OutputCREATE DATABASE
ユーザーとデータベースを作成したので、モニターを終了します
\q
Enterキーを押すと、コマンドプロンプトが表示され、続行する準備が整います。
[[step-2 -—- configuring-ufw]] ==ステップ2—UFWの設定
Initial Server Setup with Ubuntu 16.04の前提条件では、UFWを有効にし、SSH接続のみを許可しました。 設定を開始する前に、UFWのステータスを確認しましょう。
sudo ufw status
[。注意]##
Note:出力がファイアウォールがinactive
であることを示している場合、次の方法でアクティブ化できます。
sudo ufw enable
有効にした後、statusコマンドを再実行すると、sudo ufw status
に現在のルールが表示されます。 必要に応じて、SSHを許可してください。
sudo ufw allow OpenSSH
前提条件に変更を加えない限り、出力にはOpenSSHのみが許可されていることが示されます。
OutputStatus: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
ファイアウォールのステータスを確認したので、PostgreSQLポートへのアクセスを許可し、許可するホストに制限します。
以下のコマンドは、PostgreSQLのデフォルトポート(5432)のルールを追加します。 そのポートを変更した場合は、以下のコマンドで必ず更新してください。 アクセスが必要なサーバーのIPアドレスを使用していることを確認してください。 必要な場合は、このコマンドを再実行して、アクセスが必要な各クライアントIPアドレスを追加します。
sudo ufw allow from client_ip_address to any port 5432
ルールを再確認するために、ufw status
を再度実行できます。
sudo ufw status
OutputTo Action From
-- ------ ----
OpenSSH ALLOW Anywhere
5432 ALLOW client_ip_address
OpenSSH (v6) ALLOW Anywhere (v6)
[.note]#Note: UFWを初めて使用する場合は、ガイドUFW Essentials: Common Firewall Rules and Commands。
#で詳細を確認できます。
このファイアウォールルールを設定したら、PostgreSQLをパブリックIPアドレスでリッスンするように構成します。 これには、接続ホストのエントリ(pg_hba.conf
)とlisten_addressesの構成(postgresql.conf
)の2つの設定の組み合わせが必要です。
[[step-3 -—- configuring-the-allowed-hosts]] ==ステップ3—許可されたホストの構成
まず、ホストエントリをpg_hba.conf
に追加します。 異なるバージョンのPostgreSQLがインストールされている場合は、必ず以下のパスで置き換えてください。
sudo nano /etc/postgresql/9.5/main/pg_hba.conf
非ローカル接続を許可する方法を説明するコメントブロックの下にhost
行を配置します。 また、データベースサーバーのパブリックアドレスを含む行を追加して、ファイアウォールが正しく構成されていることをすばやくテストできるようにします。 以下の例では、必ずyourマシンのホスト名またはIPアドレスに置き換えてください。
pg_hba.confからの抜粋
# If you want to allow non-local connections, you need to add more
# "host" records. In that case you will also need to make PostgreSQL
# listen on a non-local interface via the listen_addresses
# configuration parameter, or via the -i or -h command line switches.
host sammydb sammy client_ip_address/32 md5
変更を保存する前に、オプションの一部を変更する場合に備えて、この行の各値に注目しましょう。
-
host最初のパラメーター
host
は、TCP / IP接続が使用されることを確立します。 -
database `sammydb` 2番目の列は、ホストが接続できるデータベースを示します。 名前をコンマで区切ることにより、複数のデータベースを追加できます。
-
user
sammy
は、接続を許可されているユーザーを示します。 データベース列と同様に、複数のユーザーをコンマで区切って指定できます。 -
addressアドレスは、クライアントマシンのアドレスを指定し、ホスト名、IPアドレス範囲、またはその他のspecial key wordsを含めることができます。 上記の例では、クライアントの単一のIPアドレスのみを許可しています。
-
auth-method最後に、auth-method、
md5
は、double-MD5-hashed passwordが認証用に提供されることを示します。 接続するユーザー用に作成されたパスワードを入力するだけです。
これらおよび追加の設定の詳細については、The pg_hba.conf
FileのPostgreSQLドキュメントを参照してください。
完了したら、ファイルを保存して終了します。
[[step-4 -—- configuring-the-listening-address]] ==ステップ4—リスニングアドレスの設定
次に、postgresql.conf
ファイルにリッスンアドレスを設定します。
sudo nano /etc/postgresql/9.5/main/postgresql.conf
listen_addresses
行を見つけ、その下でリッスンアドレスを定義します。必ず、データベースホストのホスト名またはIPアドレスに置き換えてください。 接続しているクライアントではなく、データベースサーバーのパブリックIPを使用していることを再確認してください。
postgresql.conf
#listen_addresses = 'localhost' # what IP address(es) to listen on;
listen_addresses = 'localhost,server_ip_address'
完了したら、ファイルを保存して終了します。
[[step-5 -—- restarting-postgresql]] ==ステップ5—PostgreSQLを再起動します
設定の変更は、PostgreSQLデーモンを再起動するまで有効にならないため、テストする前にそれを行います。
sudo systemctl restart postgresql
systemctl
はフィードバックを提供しないため、ステータスをチェックして、デーモンが正常に再起動したことを確認します。
sudo systemctl status postgresql
出力に「Active:active」が含まれ、次のようなもので終わる場合、PostgreSQLデーモンが実行されています。
Output...
Jan 10 23:02:20 PostgreSQL systemd[1]: Started PostgreSQL RDBMS.
デーモンを再起動したので、テストする準備ができました。
[[ステップ-6 ---テスト]] ==ステップ6—テスト
最後に、クライアントマシンから接続できることをテストしましょう。 これを行うには、psql
と-U
を使用してユーザーを指定し、-h
を使用してクライアントのIPアドレスを指定し、-d
を使用してデータベースを指定します。 sammy
が単一のデータベースにのみ接続できるようにセキュリティを強化しました。
psql -U sammy -h postgres_host_ip -d sammydb
すべてが正しく構成されている場合、次のプロンプトが表示されます。
OutputPassword for user sammy:
PostgreSQLモニターにユーザーsammy
を追加したときに設定したパスワードを入力します。
次のプロンプトが表示されたら、接続に成功しています:
[secondary_label]
sammydb=>
これにより、ファイアウォールを通過してデータベースに接続できることが確認されます。 今すぐ終了します。
\q
設定を確認したので、クリーンアップして終了します。
[[step-7 -—- removing-the-test-database-and-user]] ==ステップ7—テストデータベースとユーザーの削除
接続のテストが終了したら、ホストに戻り、次のコマンドを使用してデータベースとユーザーも削除できます。
sudo -i -u postgres psql
データベースを削除するには:
DROP DATABASE sammydb;
アクションは、次の出力によって確認されます。
OutputDROP DATABASE
ユーザーを削除するには:
DROP USER sammy;
成功は次によって確認されます。
OutputDROP ROLE
sammydb
データベースのホストエントリが不要になったため、pg_hba.conf
ファイルから削除してクリーンアップを終了します。
sudo nano /etc/postgresql/9.5/main/pg_hba.conf
pg_hba.conf
から削除する行
host sammydb sammy client_ip_address/32 md5
変更を有効にするために、保存して終了し、データベースサーバーを再起動します。
sudo systemctl restart postgresl
正常に再起動したことを確認するために、ステータスを確認します。
sudo systemctl status postgres
「アクティブ:アクティブ」と表示される場合、再起動が成功したことがわかります。
この時点で、リモートで接続する必要があるクライアントでアプリケーションまたはサービスを構成することで前進できます。
セキュリティに関する追加の考慮事項
このチュートリアルは、PostgreSQLへのセキュリティ保護されていないリモート接続を許可することによってもたらされるリスクを軽減することを目的としています。 リスニングポートへのアクセスを特定のホストに制限しても、転送中のデータを暗号化する方法など、セキュリティに関するその他の重要な考慮事項には対処しません。
実際のデータを使用する前に、次のリソースを確認し、ユースケースに適した手順を実行することをお勧めします。
-
Security within PostgreSQL:GRANTステートメントは、特定のデータベースへのアクセスを許可するユーザーを決定し、ロールはそれらのユーザーの特権を確立します。 組み合わせて、単一のインストールで複数のデータベースを分離します。
-
Setting up SSL with PostgreSQL:SSLを構成すると、転送中のデータが暗号化されます。 これにより、送信されるデータが保護されます。
-
Securing PostgreSQL TCP/IP Connections with SSH Tunnels:SSHトンネルは、SSLに対応していないクライアントと接続する場合に役立ちます。 他のほとんどの状況では、PostgresでSSLをセットアップすることをお勧めします。
結論
このチュートリアルでは、アクセスを必要とするホストからの接続のみを許可するようにサーバーのファイアウォールを構成し、それらのホストからの接続のみを受け入れるようにPostgreSQLを構成することにより、PostgreSQLインストールのアドバタイズを防ぐための重要な手順を実行しました。 これにより、特定の種類の攻撃のリスクが軽減されます。 これは、データを保護するための最初のステップにすぎません。上記の追加のセキュリティ対策を確認して実装することをお勧めします。