# UPnPによるポートマップ

* **Natを越えないとP2P通信できない**
* **UPnPを使えば、TCPでもNat越えができる**

Socketを使う事で簡単に、インターネットを利用したアプリケーションが作成する事ができます。プラウザーとかメーラーとかです。

しかし、P2Pアプリケーションを作る場合は、もう一つ考慮しなくてはならない事があります。それが、「Nat越え」です。

P2Pアプリとして、必ず満たさなければならない条件は、何でしょうか？ それは、ユーザーが所有する端末同士が直接データ通信をできる事です。P2Pの定義そのものですね。 これができません。

Nat越えをする方法はいくつかあります。本章では、UPnPを用いてNat越えをする方法について解説したいと思います。

## Global IP が必要

P2P通信するするためには、相手に自分の「IPアドレス」と「Port番号」を教える。必要ががあります。しかし、Nat越えの問題を解決しないと、これができません。

ご家庭からインターネットにアクセスする場合、ルーターというデバイスを利用しています。 ルーターは、ルータに接続している端末に 「Private IP」 を割り振ります。

```
>> netstat
```

とコマンドを入力してみましょう。「192.168.100.1」といったアドレスが端末に割り振られている事が確認できます。このアドレスを相手に伝えても、通信ができません。

### ルータから教えてもらおう

しかし、ルーターからインターネットに接続できているという事は、「Global IP」をルーターは持っているから通信できるのです。つまり、ルーターは「Global IP」をルーターは知っている。しかし、ルーターを利用している端末は「Global IP」をしらないという問題があります。

## UPnPを用いてPort Mappingをしよう

UPNPを実現するには、UDPとTCPを用いて通信できる必要があります。 具体的には、

* UDP Multicast を利用して、使用中のルーターに、ポートマッピングを依頼するためのアドレスを教えてもらう。
* TCP を使って、教えてもらったアドレスからポートマッピングの依頼をだす。

といった事をします。実際にTryしてみましょう。

### 依頼先を調べる

UDPで以下のメッセージを通知する

```
M-SEARCH * HTTP/1.1
MX: 3
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
ST: urn:schemas-upnp-org:service:WANIPConnection:1
```

もしもルーターが存在していれば、以下のような返答があります。

```
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=1800
ST: urn:schemas-upnp-org:service:WANIPConnection:1
USN: uuid:E8088BD3-E808-8BD3-A042-E8088BD3A042::urn:schemas-upnp-org:service:WANIPConnection:1
EXT:
SERVER: E588 UPnP/1.0 MiniUPnPd/1.6
LOCATION: http://192.168.100.1:54616/rootDesc.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS: 1
BOOTID.UPNP.ORG: 1
CONFIGID.UPNP.ORG: 1337
DATE: Sun, 14 Sep 2014 00:42:14 GMT
```

LOCATIONで指定されたアドレスのXMLファイルのタグの中に依頼先のアドレスが記載されています。このアドレスへ依頼をだせば、インターネットから、あなたの端末へアクセスできるようになります。

### 外部の端末から見えているアドレスを聞く

```
POST 192.168.100.1 HTTP/1.1
Host: 192.168.100.1
Connection: close
SOAPACTION: "urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
Content-Length: 324
```

成功すると、以下のような返信を受け取ります。

```
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Connection: close
Content-Length: 360
Server: E588 UPnP/1.0 MiniUPnPd/1.6
EXT:
DATE: Sun, 14 Sep 2014 01:46:07 GMT
```

### ポートマッピングの依頼をだす

```
POST 192.168.100.1 HTTP/1.1
Host: 192.168.100.1
Connection: close
SOAPACTION: "urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"
Content-Length: 629

<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV:="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body><m:AddPortMapping xmlns:m="urn:schemas-upnp-org:service:WANIPConnection:1">
<NewRemoteHost></NewRemoteHost>
<NewExternalPort>48083</NewExternalPort>
<NewProtocol>TCP</NewProtocol>
<NewInternalPort>8083</NewInternalPort>
<NewInternalClient>192.168.100.100</NewInternalClient>
<NewEnabled>1</NewEnabled>
<NewPortMappingDescription>test</NewPortMappingDescription>
<NewLeaseDuration>0</NewLeaseDuration>
</m:AddPortMapping></SOAP-ENV:Body>
</SOAP-ENV:Envelope>
```

```
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
Connection: close
Content-Length: 263
Server: E588 UPnP/1.0 MiniUPnPd/1.6
EXT:
DATE: Sun, 14 Sep 2014 01:39:27 GMT

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:AddPortMappingResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"/>
</s:Body>
</s:Envelope>
```

Kyorohiro work

<http://kyorohiro.strikingly.com>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nazenani-torrent.firefirestyle.net/upnp/about.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
