#概要
2016年初頭以降appleに申請を出すアプリに関して、義務付けられたIPv6対応に関する挙動が誤解されやすそうな気がするのでまとめる。
#テストした環境
下記に載ってるMac El CapitanにおけるDNS64/NAT64環境で構築したwifiポイント。(今後長いのでMac El CapitanにおけるDNS64/NAT64環境のwifiポイント→IPv6ポイント、と呼びます)
「Supporting IPv6 DNS64/NAT64 Networks」 / Apple
「iOS9 で必要な IPv6 only Network への対応」
これ以外でもオープンソースでDNS64/NAT64の実装はあるみたいですが、iOS端末がIPv6環境に対応してなくても動くように中でIPv6をエミュレート、みたいな動きをするらしいので多分別物だと思います。
##クライアント端末
iOS9端末(iPad mini初代 A1432)
AndroidやiOS8端末、別のMac PCからIPv6ポイントにwifi接続しようとしても、認証に問題がありますと出て繋がらなかった
#IPv6OnlyNetwork上での通信周り挙動について
Supporting IPv6 DNS64/NAT64 Networksに使うべきでない関数や定数などが列挙されています
##IPv6ポイントに接続したiOS9端末でIPv6アドレス確認
http://test-ipv6.com/
結果:IPv6 アドレスが検出されませんでした
※IPv6のない環境でアクセスしました
##IPv6ポイントからHTTPリクエスト
NSURLSessionでIPv4アドレス直打ちのアクセス
curl http://123.45.67.89/と同じレスポンス返ってきた(Apacheのテストページ)
NSURL* url = [NSURL URLWithString:@"http://123.45.67.89/"];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask* task =
[session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *str= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"str -- %@", str);
}];
[task resume];
NSURLSessionでIPv4のみのサーバーへアクセス
curl http://example.com/と同じレスポンス返ってきた
NSURL* url = [NSURL URLWithString:@"http://example.com/"];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask* task =
[session dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *str= [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"str -- %@", str);
}];
[task resume];
上記からObjective-Cの関数であれば大体何も考えなくてもAppleの審査は問題ないと思われます
※IPv4アドレス直打ちのリクエストはDNSを通していないので、そのまま繋がるみたいですが今後IPv4をなくす方向でAppleも動くはずなので出来れば変えた方が良いです
次C言語
gethostbynameとinet_ntoaでIP取得
Appleの公式では使っちゃダメって言われてるAPI
C言語なのでよく分かってませんが下記は通常通りの値が返ってくる
struct hostent *hostentry;
hostentry = gethostbyname("google.com");
char * ipbuf;
ipbuf = inet_aton(*((struct in_addr *)hostentry->h_addr_list[0]));
printf("%s",ipbuf);
inet_aton
下記も一応値が返ってくる
struct in_addr addr1;
struct in_addr addr2;
str = "173.194.120.66";//google.com
inet_aton(str, &addr1);
printf("inet_aton --------- %s = %x\n", str, addr1.s_addr);
上記どっちもAppleの公式には非推奨と書いてあるけど、一応動く
値は16進数文字列みたいのが返ってくるのでよく分からなかったけど、実行時点でエラーになるわけではなくその関数使ってIPv4リテラルを使った時にconnectしようとすると繋がらない、みたいになると思います
#WebRTCのSTUNに関する挙動
もともとWebRTCxSTUNが繋がらない理由を調べていたので、これも載せておきます
STUNはざっくり言うと外部のサーバーにリクエストすると自分のグローバルIPとポート返してくれるプロトコルです
##IPv6ポイントでも正常動作するSTUNクライアント
Objective-C STUNでググって出てきたSTUNクライアント
https://github.com/soulfly/STUN-iOS
上記でrfc5766-turn-serverで立てたSTUNサーバーにIPv6ポイントからアクセス
→正常にIPv4アドレスが戻ってくる
ソースを見るとGCDAsyncUdpSocket.mの1186行目あたりでgetaddrinfoで接続先HOSTを取得している。
Supporting IPv6 DNS64/NAT64 Networksにもあった通り、getaddrinfoなら問題ない
##IPv6ポイントでは失敗するSTUNクライアント
非常に申し訳ないですが、古いコードの例として下記を挙げさせて頂きます
https://github.com/gregnietsky/stun-c
これをXcodeにそのままコピーして、Objective-Cから呼び出して実行したところIPv6ポイントでは失敗しました。
ソースのmain関数(365行目以降)でconnect処理をしていて、AF_INET定数を使ってinet_addrで接続しています。
Supporting IPv6 DNS64/NAT64 Networksの非推奨APIでは動かない例になります。
#まとめ
NSURLSessionやCFNetwork等、Objective-Cレイヤーの通信APIはApple側で対応しているので、あまり気にしなくていい
C言語のDNS系関数はIPv4とIPv6のデュアルスタックで動くようになってないと今後iOSアプリで使えなくなる
Cやネットワーク周りが良くわかっていないので、間違っている点等あればご指摘頂けるとありがたいです