ユーザが MySQL サーバに接続しようとした場合、そのユーザ ID、およびそれを正しいパスワードで裏付けできるかどうかによって、サーバは接続の許可または拒否を行います。パスワードが正しくない場合、サーバはアクセスを完全に拒否します。正しければ、サーバは接続を許可し、段階 2 に進んで要求を待ちます。
ユーザ ID は、2 つの情報に基づきます。
接続元のホスト
MySQL ユーザ名
ID チェックには、user
テーブルの
3 つのスコープフィールド(Host
、
User
、
Password
)を使用します。user
テーブルエントリが、指定した
Host
と User
と一致し、入力したパスワードが正しい場合のみ、接続許可になります。
user
テーブルの
Host
値 (スコープ フィールド)
には次の方法で値を指定できます。
Host
値にはホスト名または IP
アドレスを使用できる。ローカルホストを指定する場合は
'localhost'
を使用する。
ワイルドカード文字
‘%
’ および
‘_
’ を
Host
フィールドに使用できる。LIKE
演算子で実行するマッチング操作と同様の効果がある。たとえば、Host
値としての '%'
はすべてのホスト名を意味する。これに対して、'%.mysql.com'
という値は mysql.com
ドメインのすべてのホスト名と一致する。
MySQL ネットワーク.
‘%
’
のような広宿主の指示子はセキュリティ
リスクをもたらします。 MySQL Network
Monitoring and Advisory Service
ではこのような脆弱性に対応するセーフガードを提供しています。詳細は
http://www-jp.mysql.com/products/enterprise/advisors.html
を参照してください。
IP アドレスとして指定する Host
値に、ネットワークアドレスを示すためのネットマスクを使用できます。次はその例です。
GRANT ALL PRIVILEGES ON db.* TO david@'192.58.197.0/255.255.255.0';
これは、david
が
client_ip
という IP
アドレスのクライアント
ホストから接続できます。これには次の条件があります。
client_ip & netmask = host_ip
つまり、GRANT
ステートメント表示です。
client_ip & 255.255.255.0 = 192.58.197.0
この条件に該当し、MySQL サーバに接続できる
IP アドレスは、192.58.197.0
から
192.58.197.255
までの範囲のもということになります。
ノート:ネットマスクの使用は 8、16、24、または 32 ビットのいずれかのアドレスを使用するようにサーバへ知らせます。たとえば、次の通りです。
192.0.0.0/255.0.0.0
: 192 クラスの
A ネットワークのすべて
192.168.0.0/255.255.0.0
: 192.168
クラスの B ネットワークのすべて
192.168.1.0/255.255.255.0
: 192.168 1
クラスの C ネットワークのすべて
192.168.1.1
: 特定の IP のみ。
次に示すネットマスク (28 ビット) は使用できません。
192.168.0.1/255.255.255.240
db
テーブル行 (エントリ) の
空白の Host
値
は、その権限が、クライアントのホスト名と一致する
host
テーブルの行のものと組み合わさるという意味です。この権限は、OR
(ユニオン) ではなく、AND
(インターセクション)
操作を使用して組み合わせられています。
host
テーブルの使用については、項4.7.6. 「アクセス制御の段階 2: 接続確認」
を参照してください。
別の権限テーブルの空白の Host
値は、'%'
と同じである。
たとえば、'144.155.166.%'
がサブネットのすべてのホストと一致する、というように、Host
カラムの IP
ワイルドカードの値を使用できるということは、ホストを
144.155.166.somewhere.com
と命名するなどして、誰かがこの機能
(セキュリティー上の弱点)
を悪用できるということです。これを阻止するために、MySQL
では、数字やドットで始まるホスト名との一致しないようになっています。つまり、1.2.foo.com
のようなホスト名の場合、この名前は、権限テーブルの
Host
カラムとは一致しないということです。IP
ワイルドカード値は、IP
アドレスとだけ一致し、ホスト名とは一致しません。
User
フィールドには、ワイルドカード文字は使用できません。空白の値は使用でき、これは任意のユーザ名と一致します。user
テーブル
エントリに空白のユーザ名があり、接続で空白ユーザーにマッチする場合、そのユーザはクライアントが実際に指定した名前のユーザではなく、匿名ユーザ(名前なしのユーザ)との解釈になります。この場合、接続中(段階
2 の間)のフル アクセス
チェックをすべて、空白のユーザ名で行うということです。
Password
フィールドは空白にできます。これはどのパスワードにも一致するという意味ではなく、そのユーザがパスワードを指定せずに接続する必要があるという意味です。
user
テーブルの空白ではない
Password
値は、暗号化パスワードを表します。 MySQL
では、パスワードを平文テキストでは保存しません。接続しようとするユーザが入力したパスワードを暗号化します(PASSWORD()
関数を使用)。クライアントおよびサーバがパスワードの確認を行うときは、その暗号化パスワードを使用します。(このとき、その接続を経由して、暗号化パスワードを転送することはありません)。注意:
MySQL
から見ると暗号化パスワードが実際のパスワードであるため、暗号化パスワードにだれにもアクセスできないようにしてください。特に、一般のユーザに
mysql
データベース内のテーブルの読み取りアクセス権を与えないでください。
MySQL 5.1 では (最初の実装は MySQL 4.1
から)、MySQL
は従来とは異なるパスワードおよびログインメカニズムを採用しています。万が一、TCP/IP
パケットの傍受や mysql
データベースのキャプチャが行なわれた場合でも安全確保できるようになっています。パスワードの暗号化に関する詳細は
項4.7.9. 「MySQL 4.1 のパスワードハッシュ」
を参照してください。
次の一覧は、user
テーブルエントリの Host
値および
User
値のさまざまな組み合わせがどのように着信の接続に適用するかを示します。
Host 値
|
User 値
|
正当な接続 |
'thomas.loc.gov' |
'fred' |
thomas.loc.gov から接続する
fred
|
'thomas.loc.gov' |
'' |
thomas.loc.gov
から接続するすべてのユーザ |
'%' |
'fred' |
任意のホストから接続するfred
|
'%' |
'' |
任意のホストから接続するすべてのユーザ |
'%.loc.gov' |
'fred' |
loc.gov ドメイン内の任意のホストから接続する
fred
|
'x.y.%' |
'fred' |
x.y.net 、x.y.com 、x.y.edu
などから接続する fred
(実用的ではない) |
'144.155.166.177' |
'fred' |
IP アドレス 144.155.166.177
のホストから接続する fred
|
'144.155.166.%' |
'fred' |
144.155.166 クラス C
サブネットの任意のホストから接続する
fred
|
'144.155.166.0/255.255.255.0' |
'fred' |
1 つ上の例と同じ |
クライアントのホスト名と着信するユーザ名が、user
テーブルのエントリ一つ以上と、一致する可能性があります。前述の例で説明すると、たとえば、thomas.loc.gov
からの fred
の接続は、前述の一覧のいくつかのエントリと一致します。
複数のエントリが一致した場合、サーバは該当するものを選択するために、次のことを行ないます。
サーバが user
テーブルをメモリに読み込むときに、エントリのソートをする。
クライアントが接続しようとすると、サーバはソート順でエントリを照会する。
サーバはクライアントのホスト名とユーザ名が一致する最初のエントリを使用する。
user
テーブルが次の内容であると仮定して、これがどのように作用するかを説明します。
+-----------+----------+- | Host | User | ... +-----------+----------+- | % | root | ... | % | jeffrey | ... | localhost | root | ... | localhost | | ... +-----------+----------+-
サーバがテーブルをメモリに読み込むと、最も具体的な
Host
値を最初にもってきます。ここでは、Host
カラムの '%'
は
「任意のホスト」
を意味し、具体性が最も低いものとなります。同じ
Host
値のエントリ間で、最も具体的な
User
値を最初にもってきます。ここでは、空白の
User
値は 「任意のユーザ」
を意味し、具体性が最も低いものとなります。ソートした
user
テーブルは次のようになります。
+-----------+----------+- | Host | User | ... +-----------+----------+- | localhost | root | ... | localhost | | ... | % | jeffrey | ... | % | root | ... +-----------+----------+-
クライアント接続が試みられると、サーバはソートしたエントリで突き合わせ
(マッチング)
を行い、最初に一致したものを使用します。localhost
からの jeffrey
による接続では、2
つのエントリが一致します
(空白ユーザ名のエントリが接続ホスト名とユーザ名の両方で一致)
。Host
と User
のカラム値をみると、'localhost'
と ''
の値が一致します。
そして、'%'
と
'jeffrey'
の値が一致します。ここで、ソートしたときに、'localhost'
が最も具体的な値であるため、これが最初に来ます。よってサーバは、表示の順序で選択します。
次に、別例を示します。user
テーブルが次の内容である場合
+----------------+----------+- | Host | User | ... +----------------+----------+- | % | jeffrey | ... | thomas.loc.gov | | ... +----------------+----------+-
ソート後のテーブルは次のようになります。
+----------------+----------+- | Host | User | ... +----------------+----------+- | thomas.loc.gov | | ... | % | jeffrey | ... +----------------+----------+-
thomas.loc.gov
からの
jeffrey
による接続は、最初のエントリを一致とし、whitehouse.gov
からの jeffrey
による接続は 2
番目のエントリとなります。
サーバが接続の突き合わせを行うとき、ユーザ名とは、明示的にそのユーザを名付けている
(ユーザであると定義している)
すべてのエントリが最初に来ると、考えることができますが、これは間違っています。上記の例でもわかるように、thomas.loc.gov
からの jeffrey
による接続は、'jeffrey'
が
User
フィールド値であるエントリではなく、ユーザ名なしのエントリと最初に一致します。つまり、jeffrey
で接続する、とユーザ名を指定したにもかわらず、彼は匿名ユーザとして認証されています。
接続したが、権限が予期したものと違うという場合、別のユーザで認証している可能性があります。サーバがどのユーザで認識が行なわれたかを突き止めるには、CURRENT_USER()
関数を (項11.10.3. 「情報関数」 参照)
使用します。(その接続に実際に一致しているユーザとホストの組み合わせを確認できます。)
そのときに、
という形の値を返します。これは、user_name
@host_name
User
と Host
のカラムの値が、user
テーブル行でどのように一致となっているのかを示します。たとえば、jeffrey
で接続して、次のようなクエリを発行したとします。
mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+
ここでの結果は、user
テーブル行で一致したものが、空白の
User
であることを示します。つまり、サーバは
jeffrey
を匿名ユーザとして扱っています。
このような認証に関わる診断をする、別の方法として、user
テーブルを出力して、それをマニュアル (手動)
でソートし、最初の組み合わせをどのような経緯でしたか調べます。