【Oracle】データベースの IP アクセス制限を行う方法|sqlnet.ora・VALID_NODE_CHECKING・ログオントリガー・OS ファイアウォールまで解説

【Oracle】データベースの IP アクセス制限を行う方法|sqlnet.ora・VALID_NODE_CHECKING・ログオントリガー・OS ファイアウォールまで解説 Oracle

Oracle データベースへの不正アクセスを防ぐ最も基本的な対策の 1 つがIP アドレスによるアクセス制限です。Oracle ではsqlnet.oraログオントリガーOS ファイアウォールの 3 つのレイヤーで IP 制限を実装できます。

本記事では、それぞれの設定方法と使い分け、サブネット指定設定変更後の反映手順自分自身を締め出さないための安全策まで解説します。

この記事でわかること
・sqlnet.ora の TCP.VALIDNODE_CHECKING / INVITED_NODES / EXCLUDED_NODES による制限
・ログオントリガーによる DB レベルの IP 制限
・OS ファイアウォール(iptables / firewalld / Windows)での制限
・3 つのレイヤーの使い分け
・サブネット / ホスト名での指定方法
・設定変更後の反映(リスナー再起動)
・自分自身を締め出さないための安全策
スポンサーリンク

IP アクセス制限の 3 つのレイヤー

レイヤー 設定場所 制限の粒度 再起動
sqlnet.ora(リスナーレベル) sqlnet.ora ファイル IP / サブネット / ホスト名 リスナー再起動が必要
ログオントリガー(DB レベル) AFTER LOGON ON DATABASE トリガー IP + ユーザー + 時間帯の組み合わせ 即時反映(DDL)
OS ファイアウォール iptables / firewalld / Windows FW IP / ポート OS コマンドで即時反映
多層防御が推奨
OS ファイアウォール: ネットワークレベルで不要なポートをブロック(1521 を許可 IP のみに限定)
sqlnet.ora: Oracle リスナーレベルで追加制限
ログオントリガー: ユーザーごとの細かい IP 制限
1 つのレイヤーだけでなく複数のレイヤーで制限するのがセキュリティのベストプラクティスです。

sqlnet.ora で IP アクセスを制限する

基本パラメータ

パラメータ 説明
TCP.VALIDNODE_CHECKING IP チェック機能の ON / OFF(YES で有効化)
TCP.INVITED_NODES 許可する IP アドレスのリスト(ホワイトリスト)
TCP.EXCLUDED_NODES 拒否する IP アドレスのリスト(ブラックリスト)
sqlnet.ora(ホワイトリスト方式: 許可 IP のみ接続可能)
# sqlnet.ora のパス:
# Linux: $ORACLE_HOME/network/admin/sqlnet.ora
# Windows: %ORACLE_HOME%\network\admin\sqlnet.ora

# IP チェックを有効化
TCP.VALIDNODE_CHECKING = YES

# 許可する IP アドレス(これ以外は全て拒否)
TCP.INVITED_NODES = (10.0.1.100, 10.0.1.101, 10.0.2.*, 192.168.1.0/24, localhost)

# ※ INVITED_NODES を設定すると、リストにない IP は全て拒否される
# ※ localhost(127.0.0.1)を必ず含めること
sqlnet.ora(ブラックリスト方式: 特定 IP だけ拒否)
TCP.VALIDNODE_CHECKING = YES

# 拒否する IP アドレス(これ以外は全て許可)
TCP.EXCLUDED_NODES = (192.168.100.50, 10.99.*)
INVITED_NODES に localhost を含めないと自分自身も接続不可になる
INVITED_NODES を設定する場合、localhost127.0.0.1必ず含めてください。含めないとサーバー上の sqlplus / as sysdba でさえ TCP 接続が拒否される場合があります。

サブネット / ワイルドカード / ホスト名の指定

指定方法 意味
IP アドレス(単体) 10.0.1.100 特定のホスト 1 台
ワイルドカード 10.0.2.* 10.0.2.0〜10.0.2.255 の全ホスト
CIDR 表記 192.168.1.0/24 192.168.1.0〜192.168.1.255(256 台)
ホスト名 app-server.example.com DNS 解決されたホスト名
localhost localhost ローカルホスト(127.0.0.1)

設定変更後の反映

Shell(リスナーの再起動)
# sqlnet.ora を編集した後はリスナーを再起動する必要がある
$ lsnrctl stop
$ lsnrctl start

# リスナーの状態を確認
$ lsnrctl status

# データベースインスタンスの再起動は不要
# (sqlnet.ora はリスナーが接続ごとに読み込む)
設定変更前のテスト手順
(1) 別ターミナルを開いておく(締め出し時の復旧用)
(2) sqlnet.ora を編集
(3) リスナーを再起動
(4) 許可した IP からの接続テスト: sqlplus hr/password@orcl
(5) 拒否すべき IP からの接続テスト(拒否されることを確認)
(6) 問題があれば sqlnet.ora を元に戻してリスナー再起動

INVITED_NODES と EXCLUDED_NODES の使い分け

方式 動作 適するケース
INVITED_NODES(ホワイトリスト) リストの IP のみ許可。それ以外は全て拒否 許可する IP が少数で明確な場合(本番環境向け)
EXCLUDED_NODES(ブラックリスト) リストの IP だけ拒否。それ以外は全て許可 拒否する IP が少数の場合(開発環境でのテスト等)
両方を同時に設定した場合
INVITED_NODES と EXCLUDED_NODES を同時に設定した場合、INVITED_NODES が優先されます。INVITED_NODES に含まれている IP は EXCLUDED_NODES に含まれていても接続可能です。混乱を避けるため、どちらか一方だけを設定することを推奨します。

ログオントリガーによる DB レベルの IP 制限

sqlnet.ora はリスナーレベルの制限で全ユーザーに一律適用されますが、ログオントリガーならユーザーごとに異なる IP 制限を設定できます。

SQL(ユーザー別 IP 制限トリガー)
CREATE OR REPLACE TRIGGER trg_ip_restrict
AFTER LOGON ON DATABASE
DECLARE
    v_ip VARCHAR2(100);
BEGIN
    -- SYS / SYSTEM は制限しない
    IF USER IN ('SYS', 'SYSTEM') THEN RETURN; END IF;

    v_ip := SYS_CONTEXT('USERENV', 'IP_ADDRESS');

    -- 管理者ユーザー: 特定 IP のみ許可
    IF USER = 'ADMIN_USER' THEN
        IF v_ip NOT IN ('10.0.1.100', '10.0.1.101') THEN
            RAISE_APPLICATION_ERROR(-20001,
                'ADMIN_USER は許可されたIPからのみ接続可能です: ' || v_ip);
        END IF;
    END IF;

    -- アプリユーザー: アプリサーバーからのみ許可
    IF USER = 'APP_USER' THEN
        IF v_ip NOT LIKE '10.0.2.%' THEN
            RAISE_APPLICATION_ERROR(-20002,
                'APP_USER はアプリサーバーからのみ接続可能です: ' || v_ip);
        END IF;
    END IF;
END;
/
SQL(許可 IP をテーブルで管理: 柔軟な方式)
-- 許可 IP テーブル
CREATE TABLE allowed_ips (
    username    VARCHAR2(30),
    ip_pattern  VARCHAR2(100),
    description VARCHAR2(200)
);

INSERT INTO allowed_ips VALUES ('ADMIN_USER', '10.0.1.100', '管理端末');
INSERT INTO allowed_ips VALUES ('ADMIN_USER', '10.0.1.101', '管理端末2');
INSERT INTO allowed_ips VALUES ('APP_USER', '10.0.2.%', 'アプリサーバー群');
COMMIT;

-- トリガー(テーブル参照版)
CREATE OR REPLACE TRIGGER trg_ip_restrict_table
AFTER LOGON ON DATABASE
DECLARE
    v_ip    VARCHAR2(100);
    v_count NUMBER;
BEGIN
    IF USER IN ('SYS', 'SYSTEM') THEN RETURN; END IF;
    v_ip := SYS_CONTEXT('USERENV', 'IP_ADDRESS');

    SELECT COUNT(*) INTO v_count FROM allowed_ips
    WHERE username = USER AND v_ip LIKE ip_pattern;

    IF v_count = 0 THEN
        -- allowed_ips に登録がないユーザーは制限なし
        SELECT COUNT(*) INTO v_count FROM allowed_ips WHERE username = USER;
        IF v_count > 0 THEN
            RAISE_APPLICATION_ERROR(-20003,
                USER || ' はIPアドレス ' || v_ip || ' からの接続が許可されていません');
        END IF;
    END IF;
END;
/
テーブル管理方式のメリット
・IP の追加/変更がトリガーの再作成なしで可能(INSERT / UPDATE だけ)
・ユーザーごとに複数の IP パターンを柔軟に設定
・allowed_ips テーブルに未登録のユーザーは制限なし(全 IP 許可)

ログオントリガーの詳細は「ユーザーごとに接続制限を設定する方法」も参照してください。

OS ファイアウォールでの制限

Shell(Linux: firewalld)
# Oracle リスナーポート 1521 を特定 IP のみに開放
# (1) デフォルトで 1521 をブロック
firewall-cmd --permanent --remove-port=1521/tcp

# (2) 許可 IP からの 1521 のみ開放
firewall-cmd --permanent --add-rich-rule='
    rule family=ipv4 source address=10.0.1.0/24 port port=1521 protocol=tcp accept'
firewall-cmd --permanent --add-rich-rule='
    rule family=ipv4 source address=192.168.1.50 port port=1521 protocol=tcp accept'

# (3) 反映
firewall-cmd --reload
Shell(Linux: iptables)
# 特定 IP のみ 1521 を許可
iptables -A INPUT -p tcp --dport 1521 -s 10.0.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 1521 -s 192.168.1.50 -j ACCEPT
iptables -A INPUT -p tcp --dport 1521 -j DROP

# 設定の永続化
service iptables save
Shell(Windows: netsh)
# Windows ファイアウォールで 1521 を特定 IP のみに許可
netsh advfirewall firewall add rule name="Oracle 1521" dir=in action=allow protocol=tcp localport=1521 remoteip=10.0.1.0/24,192.168.1.50
OS レイヤー メリット デメリット
OS ファイアウォール Oracle に到達する前にブロック。最も堅牢 Oracle のユーザーごとの細かい制御は不可
sqlnet.ora Oracle リスナーレベルで制御。OS 設定権限不要 リスナー再起動が必要。ユーザー別制御は不可
ログオントリガー ユーザーごとに異なる IP を許可 / 拒否 DB 接続後のチェック(TCP 接続自体は通る)

設定変更後のテスト

Shell(接続テスト)
# 許可された IP から接続テスト
sqlplus hr/password@//db-server:1521/orcl
# → 接続成功すれば OK

# 拒否されるべき IP から接続テスト
sqlplus hr/password@//db-server:1521/orcl
# → ORA-12537: TNS:connection closed
# → ORA-12170: TNS:Connect timeout occurred

# リスナーログで拒否を確認
# tail -f $ORACLE_BASE/diag/tnslsnr/*/listener/alert/log.xml
SQL(DB レベルの接続元 IP を確認)
-- 現在接続中のセッションの IP アドレスを確認
SELECT sid, serial#, username,
       SYS_CONTEXT('USERENV', 'IP_ADDRESS') AS client_ip,
       SYS_CONTEXT('USERENV', 'HOST') AS client_host
FROM v$session
WHERE username IS NOT NULL
ORDER BY username;

自分自身を締め出さないための安全策

# 安全策
1 別ターミナルを開いたまま設定を変更する(締め出し時に元に戻せるように)
2 INVITED_NODES に localhost と 127.0.0.1 を必ず含める
3 sqlnet.ora 編集前にバックアップを取る: cp sqlnet.ora sqlnet.ora.bak
4 変更後すぐに接続テストを行い、問題があればバックアップから戻す
5 OS レベルでは sqlplus / as sysdba(OS 認証)で常にログイン可能にしておく
最悪の場合の復旧手順
sqlnet.ora の設定ミスで全 IP からの接続がブロックされた場合:
(1) DB サーバーにコンソールまたは SSH でログイン
(2) sqlnet.ora のバックアップを戻す: cp sqlnet.ora.bak sqlnet.ora
(3) リスナーを再起動: lsnrctl stop; lsnrctl start
sqlplus / as sysdba(OS 認証)は sqlnet.ora の影響を受けないため、DB の操作は可能です。

実務パターン集

パターン(1): 本番 DB を社内ネットワークのみに制限

sqlnet.ora
TCP.VALIDNODE_CHECKING = YES
TCP.INVITED_NODES = (10.0.0.0/8, 192.168.0.0/16, localhost, 127.0.0.1)

パターン(2): アプリサーバー + DBA 端末のみ許可

sqlnet.ora
TCP.VALIDNODE_CHECKING = YES
TCP.INVITED_NODES = (
    10.0.2.10,     # アプリサーバー1
    10.0.2.11,     # アプリサーバー2
    10.0.1.50,     # DBA 端末
    localhost,
    127.0.0.1
)

パターン(3): 開発環境で特定の不正 IP だけブロック

sqlnet.ora
TCP.VALIDNODE_CHECKING = YES
TCP.EXCLUDED_NODES = (192.168.100.50, 10.99.*)

パターン(4): sqlnet.ora + トリガーの多層防御

設定例
# --- sqlnet.ora: 社内ネットワークのみ許可 ---
TCP.VALIDNODE_CHECKING = YES
TCP.INVITED_NODES = (10.0.0.0/8, localhost, 127.0.0.1)

# --- ログオントリガー: DBA ユーザーはさらに端末を限定 ---
# CREATE OR REPLACE TRIGGER trg_ip_restrict ...
# IF USER = 'DBA_USER' AND v_ip NOT IN ('10.0.1.50') THEN ...

よくある質問

Qsqlnet.ora の変更にデータベースの再起動は必要ですか?
A不要です。sqlnet.ora はリスナーが接続ごとに読み込むため、リスナーの再起動だけで反映されます(lsnrctl stop; lsnrctl start)。データベースインスタンスの再起動は不要です。
QINVITED_NODES と EXCLUDED_NODES を同時に設定するとどうなりますか?
AINVITED_NODES が優先されます。INVITED_NODES に含まれている IP は EXCLUDED_NODES に含まれていても接続可能です。混乱を避けるためどちらか一方だけを設定することを推奨します。
Qsqlplus / as sysdba は IP 制限の影響を受けますか?
Asqlplus / as sysdba(OS 認証)はTCP 接続を経由しないため、sqlnet.ora の IP 制限の影響を受けません。設定ミスで全 IP がブロックされても、サーバー上でのローカル接続は可能です。
Qログオントリガーで IP が NULL になることがあります
Aサーバー上でのローカル接続(sqlplus / as sysdba)の場合、SYS_CONTEXT('USERENV', 'IP_ADDRESS') は NULL を返すことがあります。トリガー内で NULL のケースを考慮してください(NULL なら制限なしとするのが安全です)。
Qワイルドカード(*)と CIDR 表記(/24)はどちらを使うべきですか?
Aどちらも機能しますが、CIDR 表記の方が正確です。10.0.2.*10.0.2.0/24 と同等ですが、/1610.0.0.0/16)のような広い範囲はワイルドカードでは 10.0.* と書く必要があり、CIDR の方が明確です。
QOS ファイアウォールと sqlnet.ora のどちらで制限すべきですか?
A両方で制限するのがベストです。OS ファイアウォールは Oracle に到達する前にブロックするため最も堅牢です。sqlnet.ora は OS の設定権限がなくても DBA だけで設定できるメリットがあります。

まとめ

IP アクセス制限の要点をまとめます。

やりたいこと 方法
特定 IP のみ接続許可(リスナーレベル) sqlnet.ora: TCP.VALIDNODE_CHECKING=YES + TCP.INVITED_NODES
特定 IP だけ拒否 sqlnet.ora: TCP.VALIDNODE_CHECKING=YES + TCP.EXCLUDED_NODES
ユーザーごとに IP を制限 AFTER LOGON ON DATABASE トリガー + SYS_CONTEXT(‘USERENV’,’IP_ADDRESS’)
ネットワークレベルでポートをブロック OS ファイアウォール(firewalld / iptables / Windows FW)
多層防御(最も安全) OS ファイアウォール + sqlnet.ora + ログオントリガー
設定変更の反映 lsnrctl stop; lsnrctl start(DB 再起動は不要)

リスナー設定の詳細は「リスナー設定完全解説」、ユーザーごとの接続制限は「ユーザーごとに接続制限を設定する方法」も併せて参照してください。