

環境はconohaのVPS(CentOS6.5)をレンタルしています。  
PHPは5.6です。

conohaでは標準os(CentOS6.5)を選択した場合、17個IPv6がついてきます。  
IPv4を追加するのは有料なので、できるだけIPv6を活用したいと思っています。

file_get_contentsにてコンテキストの使用が可能ということでPHPマニュアルにある以下のコードを試してみました。

[code]

    <?php
    $opts = array(
    　　　　'socket' => array(
    　　　　　　　　'bindto' => '[自環境のIPv6]:任意のポート',
    　　　　),
    );
    
    $context = stream_context_create($opts);
    echo file_get_contents('http://www.example.com', false, $context);
    
    ?>
    
[/code]

上記のようにコンテキストを指定しても

  * file_get_contents(): Invalid IP Address : [自環境のIPv6]

というエラーが出てしまいます。

以下状況です。

  * 当該のIPv6は17個すべてDNS逆引きが可能な状態で設定は正しいものと思います。
  * IPv6、17個すべて試しましたがエラーが出ます(省略表記・フル表記どちらも）。
  * 別途追加したIPv4ではコンテキスト指定（IP切り替え）に成功しています。
  * 接続先のサイトはIPv6に対応しています。 

どのようにしたらPHPからIPv6にて外部に出ることができますでしょうか？  
IP(IPv6にて)を切り替えてデータが取得できるのであれば方法はfile_get_contentsにこだわりはありません。

よろしくおねがいします。

追記 コメントにて確認頂いた件について情報を追加

  * 1．ping6は成功しています。( ipv6.google.com等のサイトで成功）
  * 2．ip6tablesの設定は以下です。

:INPUT ACCEPT [0:0]  
:FORWARD ACCEPT [0:0]  
:OUTPUT ACCEPT [0:0]  
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT   
-A INPUT -p ipv6-icmp -j ACCEPT -A INPUT -i lo -j ACCEPT  
-A INPUT -m state --state NEW -m udp -p udp --dport 546 -d [ 自環境のIPv6の帯域] -j ACCEPT   
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT  
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited   
-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited   
COMMIT

  * 3．ip6tablesを無効にしても出現するエラーに変化はありませんでした。  

  * 4．`php -i | grep -i ipv6`の試行結果については以下のようになりました。

$ php -i | grep -i ipv6  
IPv6 Support => enabled  
IPv6 => Yes

  * 5．PHPプログラムのbindtoの部分を`'bindto' => '[0]:0'` (osに任せる)にしてみる。

エラーは出なくなりますが、別途所有するサーバに以下のようなスクリプトを用意し接続してみると、取得できるのはインターフェスeth0に紐付いたVPSレンタル時に授与されるデフォルトのIPv4でした。

[code]

        <?php
        echo $_SERVER["REMOTE_ADDR"];
    
[/code]

  * 6．'bindto' => '[::1]:0'の試行結果は以下のようになりました。

以下のようなエラーとなりました。

file_get_contents(): Invalid IP Address: ::1

上記5.で使用した別サーバのスクリプトにて取得できたIPはデフォルトのIPv4でした。

  * 7．IPアドレスとして適切な形式になってるかの確認（全角文字の有無、省略表記の誤謬)

再度確認しましたが、全角文字等の不適当な文字は入っていませんでした。  
::が:になっていないかについては、所有するIPv6にて0000で連続する領域が無いため記述はありません。  
また、所有するIPv6にて「0090」のような「0」を省略できる箇所は複数ありますので、再度省略に間違いがないかを確認しました。また0を省略しないフル表記でも再度試行してみましたが、エラーは依然として出ています。

  * 一応の解決？

結論から申しますと、コメントにて示唆いただいた「IPv6の直指定によるfile_get_contents」にて、IPv6コンテキスト切り替えが可能であることがわかりました。

IPv6の直指定であれば、エラーは出ず、なおかつ接続元のIPはIPv6になります。ドメイン指定でなぜエラーが出てしまうのかの疑問はありますが、現状では示唆していただいた方法で目的に叶うので一旦解決とさせていただきたいと思います。

たくさんの助言をいただきありがとう御座います。


CC BY-SA 3.0
2015-11-17T06:46:00.390
18937
2015-11-21T01:25:47.950
2015-11-21T01:25:47.950
13295
13295
question
php linux centos ipv6
PHPにてfile_get_contentsでのIPv6の使用について（外部に出る際のIPの切り替え）


ソースコードを見ると"Invalid IP
Address"になるのは文字列がIPアドレスとして適切な形式になっていない場合なので、その点を確認してください。

・全角文字を紛れ込ませていないか  
・0を省略する`::`が`:`になっていないか

など

もう一つ、接続先がIPv4の場合、IPv6アドレスを表記していてもIPv4として解釈しようとしてやはり"Invalid IP Address"になります。

[code]

    $ host www.google.com
    www.google.com has address 173.194.126.209
    www.google.com has address 173.194.126.212
    www.google.com has address 173.194.126.208
    www.google.com has address 173.194.126.210
    www.google.com has address 173.194.126.211
    www.google.com has IPv6 address 2404:6800:4004:808::1010
    
    file_get_contents('http://www.google.com', false, $context);
    // => no warning
    
    $ host www.yahoo.co.jp
    www.yahoo.co.jp is an alias for www.g.yahoo.co.jp.
    www.g.yahoo.co.jp has address 182.22.72.251
    www.g.yahoo.co.jp has address 183.79.197.250
    www.g.yahoo.co.jp has address 183.79.198.79
    www.g.yahoo.co.jp has address 183.79.227.90
    
    file_get_contents('http://www.yahoo.co.jp', false, $context);
    // => PHP Warning:  file_get_contents(): Invalid IP Address: (snip)
    
[/code]


CC BY-SA 3.0
2015-11-19T09:50:54.173
19044
2015-11-20T00:52:26.153
2015-11-20T00:52:26.153
5793
5793
18937
answer