<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>STUN &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/stun/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>壁を越えろ！WebRTCでNAT/Firewallを越えて通信しよう</title>
		<link>/mganeko/5554/</link>
		<pubDate>Tue, 11 Mar 2014 01:00:31 +0000</pubDate>
		<dc:creator><![CDATA[がねこまさし]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[STUN]]></category>
		<category><![CDATA[TURN]]></category>
		<category><![CDATA[WebRTC]]></category>

		<guid isPermaLink="false">/?p=5554</guid>
		<description><![CDATA[連載： WebRTCを使ってみよう！ (5)こんにちは！がねこまさしです。前回は複数人の同時通話まで実現しました。社内で使うには十分なレベルです。 しかし本格的な企業ユースとなると、まだまだ障害があります。会社と家、自社...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/webrtc-beginner/" class="series-158" title="WebRTCを使ってみよう！" data-wpel-link="internal">WebRTCを使ってみよう！</a> (5)</div><p>こんにちは！がねこまさしです。<a href="https://html5experts.jp/mganeko/5438/" title="シグナリングサーバーを応用！ 「WebRTCを使って複数人で話してみよう」" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">前回は複数人の同時通話まで実現</a>しました。社内で使うには十分なレベルです。<br />
しかし本格的な企業ユースとなると、まだまだ障害があります。会社と家、自社と別の会社さんなど、実際に通信しようとするとNATやFirewallといった壁が立ちはだかります。</p>

<h2>NATを越えよう</h2>

<h3>NATの役割は</h3>

<p><a href="http://ja.wikipedia.org/wiki/ネットワーク%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E5%A4%89%E6%8F%9B" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">NAT(+IPマスカレード)</a>は企業だけでなく、一般家庭でも使われています。ブロードバンドルーターやWiFiルーターでは、1つのグローバルIPアドレスを、複数のPCやデバイスで共有することができます。このとき、NATには2つの役割があります。</p>

<ul>
    <li>インターネットにつながったグローバルなIPアドレスと、家庭内/社内のローカルなネットワークでのIPアドレスの変換</li>
    <li>複数のPC/デバイスが同時に通信できるように、ポートマッピングによるポート変換</li>
</ul>

<p>WebRTCでNAT越しに通信すること考えてみましょう。</p>

<h4>ブラウザが知っている情報</h4>

<ul>
    <li>ローカルネットワークのIPアドレス:A</li>
    <li>自分が使う（動的に割り振った)UDPポート:A/UDP</li>
</ul>

<h4>ブラウザでは分からない情報</h4>

<ul>
    <li>グローバルIPアドレス:A&#8217;</li>
    <li>NATによってマッピングされた、外部に向けたUDPポート:A&#8217;/UDP</li>
</ul>

<p>Peer-to-Peer通信を行うには、シグナリング処理でお互いに（ローカルネットワーク内の情報ではなく）インターネット側から見た情報を通知する必要があります。<br />
<a href="https://html5experts.jp/wp-content/uploads/2014/03/webrtc_nat_0.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/03/webrtc_nat_0-300x204.png" alt="webrtc_nat_0" width="300" height="204" class="alignnone size-medium wp-image-5559" srcset="/wp-content/uploads/2014/03/webrtc_nat_0-300x204.png 300w, /wp-content/uploads/2014/03/webrtc_nat_0-207x141.png 207w, /wp-content/uploads/2014/03/webrtc_nat_0.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
ブラウザーが、インターネット側から見た情報を知るための仕組みが、STUNになります。</p>

<h3>STUNの仕組みは</h3>

<p>STUNの仕組みは意外とシンプルです。インターネット側にいる誰か（STUNサーバー）に、自分（ブラウザ）がどう見えるか教えてもらうだけです。<br />
<a href="https://html5experts.jp/wp-content/uploads/2014/03/webrtc_nat_1.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/03/webrtc_nat_1-300x213.png" alt="webrtc_nat_1" width="300" height="213" class="alignnone size-medium wp-image-5562" srcset="/wp-content/uploads/2014/03/webrtc_nat_1-300x213.png 300w, /wp-content/uploads/2014/03/webrtc_nat_1-207x147.png 207w, /wp-content/uploads/2014/03/webrtc_nat_1.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
STUNは元々WebRTCのために作られた仕組みではなく、より汎用的なUDP通信の補助として生まれました。VoIPやネットワークゲームの世界でも使われているようです。
<br /><br />
自分を外側から見た情報が分かったら、それをシグナリングサーバー経由で通信相手に渡します。<br />
<a href="https://html5experts.jp/wp-content/uploads/2014/03/webrtc_nat_2.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/03/webrtc_nat_2-300x213.png" alt="webrtc_nat_2" width="300" height="213" class="alignnone size-medium wp-image-5565" srcset="/wp-content/uploads/2014/03/webrtc_nat_2-300x213.png 300w, /wp-content/uploads/2014/03/webrtc_nat_2-207x147.png 207w, /wp-content/uploads/2014/03/webrtc_nat_2.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
お互いの情報が伝わったら、そこを目掛けて通信を行います。間にNATが挟まりますが、ポートを直接マッピングしているのであくまでもPeer-to-Peerです。<br />
<a href="https://html5experts.jp/wp-content/uploads/2014/03/webrtc_nat_3.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/03/webrtc_nat_3-300x215.png" alt="webrtc_nat_3" width="300" height="215" class="alignnone size-medium wp-image-5566" srcset="/wp-content/uploads/2014/03/webrtc_nat_3-300x215.png 300w, /wp-content/uploads/2014/03/webrtc_nat_3-207x148.png 207w, /wp-content/uploads/2014/03/webrtc_nat_3.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a><br /></p>

<h3>STUNサーバーを動かそう</h3>

<p>それでは実際にSTUNサーバーを動かしてみましょう。Linuxで動作するオープンソースのものがあるので、そちらを使います。<br />
<a href="https://code.google.com/p/rfc5766-turn-server/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><strong>rfc5766-turn-server</strong></a><br />
このサーバはSTUNだけでなく、後程説明するTURNにも対応しています。<br />
DownloadページからOSに合わせたgzファイルをダウンロードし、INSTALL手順に従ってビルド、インストールしてください。参考までに以前私が実施した手順を載せておきます。※ちょっと古いバージョンです。最新のものを取得してインストールしてください。
</p><pre class="crayon-plain-tag">$ wget https://rfc5766-turn-server.googlecode.com/files/turnserver-3.2.1.4-CentOS6-x86_64.tar.gz
$ tar zxvf turnserver-3.2.1.4-CentOS6-x86_64.tar.gz
$ cd turnserver-3.2.1.4
$ ./install.sh</pre><p> 
CentOSの場合、以下の場所に導入されました。
</p><pre class="crayon-plain-tag">バイナリ &rarr;  /usr/bin/turnserver 
設定ファイル &rarr;  /etc/turnserver/*.conf</pre><p></p>

<p>次に設定ファイル( /etc/turnserver/turnserver.conf )を見てみましょう。ポイントとなるのは次の箇所です。
</p><pre class="crayon-plain-tag"># STUN/TURNサーバーの接続待ポート番号。デフォルトは3478です。
# コメントアウトを外して数値を指定すれば、任意のポートに変更できます。 
#
# TURN listener port for UDP and TCP (Default: 3478).
# Note: actually, TLS &amp;amp; DTLS sessions can connect to the
# &quot;plain&quot; TCP &amp;amp; UDP port(s), too - if allowed by configuration.
#
#listening-port=3478</pre><p>
TCPとUDPの両方で待ち受けできますが、STUNはUDPのみが有効なので注意が必要です。※つまりUDPが通らない環境ではSTUNは使えません。</p>

<p></p><pre class="crayon-plain-tag"># このサーバーはデフォルトでSTUN/TURNの両方をサポートしています。
# STUNのみ使いたい場合は、stun-only のコメントアウトを外します。
#
# Option to suppress TURN functionality, only STUN requests will be processed.
# Run as STUN server only, all TURN requests will be ignored.
# By default, this option is NOT set.
#
#stun-only</pre><p>
STUNはPeer-to-Peer通信が始まればサーバーのCPU負荷、ネットワーク負荷はかかりません。それに対して後述するTURNでは特にネットワーク負荷がかかります。サーバーを借りていてネットワーク通信量で課金されるようなケースでは、stun-onlyを設定してTURNは無効にしておいた方が良いかもしれません。<br /><br />
設定がすんだらSTUNサーバーを起動してみましょう。画面にエラーが出なければ無事に起動成功です。エラーが出る場合は turnserver.conf を確認してみてください。
</p><pre class="crayon-plain-tag">/usr/bin/turnserver -o -v -c /etc/turnserver/turnserver.conf</pre><p></p>

<h3>クライアントのソースを修正しよう</h3>

<p>ここまでで準備したSTUNサーバーを使うように、クライアント側のソースを修正しましょう。<a href="https://html5experts.jp/mganeko/5438/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">前回</a>のソースの一部を変更します。<br />
STUNサーバーが stun.yourdomain.com で、デフォルトのポート3478で動いていると仮定します。その情報をPeerConnectionに教えてあげます。
</p><pre class="crayon-plain-tag">function prepareNewConnection(id) {
  var pc_config = {"iceServers":[ {"url":"stun:stun.yourdomain.com:3478"} ]};
  var peer = null;
  try {
    peer = new webkitRTCPeerConnection(pc_config);
  } catch (e) {
    console.log("Failed to create PeerConnection, exception: " + e.message);
  }

  //...省略...
}</pre><p> 
さあ、これで接続を試してください。上手く行けば、自宅と友人の家で通信が可能になっているはずです。</p>

<h3>STUNでNATを越えられないとき</h3>

<p>NATにはグローバルIPアドレスを共有するだけでなく、セキュリティ対策としての役割もあります。内部の端末を隠したり、通信できるポートを制限したり、一種の簡易Firewallとして利用されているケースもあります。その場合はFirewallの場合と同じく、次に説明するTURNを利用する必要があります。<br />
また、NATの構造によっては、接続先によって（今回の場合、STUNサーバーとPeer-to-Peerの通信相手）別のポートが割り当てられる Symmetric NAT という物があります。この場合もSTUNの仕組みでは通信することができません。やはりTURNの出番ということになります。</p>

<h2>Firewallを越えよう</h2>

<p>一般家庭のようにブロードバンドルーターなどでNATがある環境では、STUNを使えば通信が可能になります。次は一般的な企業で使えるようにしましょう。<br />
企業ではFirewallが設置されているケースがほとんどです。その場合、外部と通信できるポートも制限されます。STUNではUDPポートは動的に割り振られるままなので、Firewallにとても大きな穴を空けないと通信ができません。きっとセキュリティ管理者に怒られてしまいます。こんなケースに対応するのが、TURNの仕組みです。TURNもWebRTCのために生まれたのではなく、VoIPやネットワークゲームの世界で使われていたものです。</p>

<h3>TURNの仕組みは</h3>

<p>TURNを使った通信では、TURNサーバが実際のストリームデータを受け渡す間に入ります。すべてのパケットをTURNサーバーがリレーすることになり、もはやPeer-to-Peer通信ではなくなります。この際TURNサーバーでは動画のエンコーディングは行わないので、CPU負荷よりもネットワーク負荷が高くなりやすいです。<br />
<a href="https://html5experts.jp/wp-content/uploads/2014/03/webrtc_fw_1.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/03/webrtc_fw_1-300x222.png" alt="webrtc_fw_1" width="300" height="222" class="alignnone size-medium wp-image-5593" srcset="/wp-content/uploads/2014/03/webrtc_fw_1-300x222.png 300w, /wp-content/uploads/2014/03/webrtc_fw_1-207x153.png 207w, /wp-content/uploads/2014/03/webrtc_fw_1.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<h3>Firewallに穴を空けよう</h3>

<p>TURNを使うには、Firewallに1つ穴を空ける必要があります。標準では3478/UDPを使うので、そのポートが通過可能になるように設定して（してもらって）ください。<br />
もう1つ、シグナリングサーバーと通信するための穴も空ける必要があります。例えば9000番を使うのであれば、9000/TCPも同様に通過可能になるように設定して（してもらって）ください。<br />
会社間で通信するのは、両方の会社でFirewallに穴を空ける必要があります。<br />
※これを読んで「結局Firewallをいじるのかよー」とがっかりした人もいますよね？　Firewallをいじらない方法もあるので、最後までお楽しみに。</p>

<h3>TURNサーバーを動かそう</h3>

<p>TURNサーバーは先ほどSTUNサーバーとしてインストールした<a href="https://code.google.com/p/rfc5766-turn-server/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><strong>rfc5766-turn-server</strong></a><br />がそのまま使えます。/etc/turnserver/turnserver.conf の設定を変更してTURNとして使える様にします。
</p><pre class="crayon-plain-tag"># STUN/TURNサーバーの接続待ポート番号。デフォルトは3478です。
# コメントアウトを外して数値を指定すれば、任意のポートに変更できます。 
#
# TURN listener port for UDP and TCP (Default: 3478).
# Note: actually, TLS &amp;amp; DTLS sessions can connect to the
# &quot;plain&quot; TCP &amp;amp; UDP port(s), too - if allowed by configuration.
#
#listening-port=3478</pre><p>
デフォルトのポートは3478ですが、自由に設定できます。<br />
</p><pre class="crayon-plain-tag"># UDP/IPの他に、rfc5766-turn-serverではTLS/DTLSでの通信も可能です（デフォルトで有効になっています）
# 残念ながらブラウザー側の実装がまだ不十分なので、この機能は無効にしておく（コメントアウトを外す）ことをお勧めします

# Uncomment if no TLS client listener is desired.
# By default TLS client listener is always started.
#
no-tls

# Uncomment if no DTLS client listener is desired.
# By default DTLS client listener is always started.
#
no-dtls</pre><p>
TLS/DTLSは今回は使わない設定にしておきます。また先ほどのSTUNを動かす際に stun-only を設定した場合は、再びコメントアウトしてTURNも使える様にして下さい。
</p><pre class="crayon-plain-tag"># Option to suppress TURN functionality, only STUN requests will be processed.
# Run as STUN server only, all TURN requests will be ignored.
# By default, this option is NOT set.
#
#stun-only</pre><p></p>

<p><br />
そして、WebRTCでTURNを使う際のキモはこちらの設定です。
</p><pre class="crayon-plain-tag"># 認証の方法を選択します。次の3種類があります。
#   no-auth
#   st-cred-mech (short-term credential mechanism) 
#   lt-cred-mech (long-term credential mechanism) 
# WebRTCでは lt-cred-mechを使用する必要がありますので、その行のコメントアウトを外します。

# Uncomment to use long-term credential mechanism.
# By default no credentials mechanism is used (any user allowed).
# This option can be used with either flat file user database or
# PostgreSQL DB or MySQL DB or Redis DB for user keys storage.
#
lt-cred-mech

# 同時に、realmも設定が必要になります。お忘れなく。
#
# Realm for long-term credentials mechanism and for TURN REST API.
#
realm=turn.yourdomain.com</pre><p>
なかなか lt-cred-mech が必須だとは分からず、とても長い間悩んでしまいました。lt-cred-mech で使用するアカウント情報はPostgreSQL, MySQL, Redisなどで管理できますが、今回はシンプルにファイル管理にします。
</p><pre class="crayon-plain-tag"># ユーザーアカウントを定義するファイル名を指定します。 
#
# 'Dynamic' user accounts database file name.
# Only users for long-term mechanism can be stored in a flat file,
# short-term mechanism will not work with option, the short-term
# mechanism required PostgreSQL or MySQL or Redis database.
# 'Dynamic' long-term user accounts are dynamically checked by the turnserver process,
# so that they can be changed while the turnserver is running.
#
# Default file name is turnuserdb.conf.
#
userdb=/etc/turnserver/turnuserdb.conf</pre><p></p>

<p>/etc/turnserver/turnuserdb.conf を使うことにしたので、その内容も変更します。
</p><pre class="crayon-plain-tag">#This file can be used as user accounts storage for long-term credentials mechanism.
#
#username1:key1
#username2:key2
# OR:
#username1:password1
#username2:password2
yourid:yourpassword</pre><p>
例としてユーザID: yourid 、パスワード: yourpassword　としました。　※実際にはもっと強度の高いパスワードにしてくださいね。<br />
<br />
これで turnserverを再起動すれば、TURNでの通信が有効になります。
</p><pre class="crayon-plain-tag">/usr/bin/turnserver -o -v -c /etc/turnserver/turnserver.conf</pre><p>
※ちなみに turnserverを安全に停止させる手段が分かりません。仕方がないので kill で殺しています&#8230;。</p>

<h3>クライアントのソースを修正しよう</h3>

<p>ここまでで準備したTURNサーバーを使うように、クライアント側のソースを修正しましょう。STUNで修正した部分と同じ個所になります。
STUN/TURNサーバーが turn.yourdomain.com で、デフォルトのポート3478で動いていると仮定します。その情報をPeerConnectionに教えてあげます。（STUNとTURNの両方を候補にすることができます）
</p><pre class="crayon-plain-tag">function prepareNewConnection(id) {
  var pc_config = {"iceServers":[
   {"url":"stun:turn.yourdomain.com:3478"},
   {"url":"turn:turn.yourdomain.com:3478", "username":"yourid", "credential":"yourpassword"}
  ]};
  var peer = null;
  try {
    peer = new webkitRTCPeerConnection(pc_config);
  } catch (e) {
    console.log("Failed to create PeerConnection, exception: " + e.message);
  }

  //...省略...
}</pre><p>
さあ、これで接続を試してください。上手く行けば、会社と自宅、あるいは会社と友人の会社で通信が可能になります。</p>

<h2>Firewallはそのままで</h2>

<p>実際の企業ではセキュリティ上の制約や手続き上の問題で、Firewallに穴を空けるのが大変なことも多々あります。お客様の会社だったらなおさらですよね。そんな時のために、TURN over TCP という規格があり、rfc5766-turn-server と Chrome の両方ともサポートしてます。これを使えば、Firewallはそのままで、通信が可能になります。</p>

<h3>TURNサーバを設定し直そう</h3>

<p></p><pre class="crayon-plain-tag"># 一つのポート番号で、UDPとTCPの両方を待ち受けすることができます。
# HTTPと同じ、80番を設定します。
#
# TURN listener port for UDP and TCP (Default: 3478).
# Note: actually, TLS &amp;amp; DTLS sessions can connect to the
# &quot;plain&quot; TCP &amp;amp; UDP port(s), too - if allowed by configuration.
#
listening-port=80</pre><p>
設定が終わったら、turnserverを再起動してください。</p>

<h3>クライアントのソースを修正しよう</h3>

<p></p><pre class="crayon-plain-tag">function prepareNewConnection(id) {
  var pc_config = {"iceServers":[
   {"url":"stun:turn.yourdomain.com:80"},
   {"url":"turn:turn.yourdomain.com:80?transport=udp", "username":"yourid", "credential":"yourpassword"},
   {"url":"turn:turn.yourdomain.com:80?transport=tcp", "username":"yourid", "credential":"yourpassword"}
  ]};
  var peer = null;
  try {
    peer = new webkitRTCPeerConnection(pc_config);
  } catch (e) {
    console.log("Failed to create PeerConnection, exception: " + e.message);
  }

  //...省略...
}</pre><p>
ここでは省略しますが、シグナリングサーバーも 80/TCP で動かす必要があります。サーバー側のNode.jsのポート番号と、クライアント側のsocket.ioのつなぎ先のポート番号を80番に変更してください。※Webサーバー、シグナリングサーバー、TURNサーバーの3つをすべて80/TCPで動かすので、サーバーを3つ別々に立てる必要があります。頑張ってください。<br />
<a href="https://html5experts.jp/wp-content/uploads/2014/03/webrtc_fw_80.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/03/webrtc_fw_80-300x226.png" alt="webrtc_fw_80" width="300" height="226" class="alignnone size-medium wp-image-5601" srcset="/wp-content/uploads/2014/03/webrtc_fw_80-300x226.png 300w, /wp-content/uploads/2014/03/webrtc_fw_80-207x156.png 207w, /wp-content/uploads/2014/03/webrtc_fw_80.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
さあ、これで最後です。ブラウザをリロードしてください。きっと壁を越えて対話ができることと思います。</p>

<h2>最後に</h2>

<p>これまで全5回、WebRTCの使いかたを説明してきました。開発者向けにコードを一から書いてきましたが、世の中には便利なライブラリやサービスも数多くあります。</p>

<ul>
    <li><a href="https://html5experts.jp/yusuke-naka/3693/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">WebRTC開発者向けライブラリ「PeerJS」はこうして作られた</a></li>
<li><a href="https://html5experts.jp/yusuke-naka/1130/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">WebRTCで注目された海外企業のサービス19本一挙公開</a></li>
</ul>

<p>こちらを利用するのもありですね。日本でWebRTCが盛り上がって、企業ユースでも認知されるのを期待しています。<br />
おつきあいいただき、どうもありがとうございました。<br />
<img src="/wp-content/uploads/2014/03/thankyou-300x216.png" alt="thankyou" width="200" class="alignnone size-medium wp-image-5611" srcset="/wp-content/uploads/2014/03/thankyou-300x216.png 300w, /wp-content/uploads/2014/03/thankyou-207x149.png 207w, /wp-content/uploads/2014/03/thankyou.png 559w" sizes="(max-width: 300px) 100vw, 300px" /></p>
]]></content:encoded>
		
		<series:name><![CDATA[WebRTCを使ってみよう！]]></series:name>
	</item>
	</channel>
</rss>
