curlでポートマッピング【UPnP】

# `Location`を取得する

**192.168.10.1**はデフォルトゲートウェイ

### PowerShell
```powershell
$client = New-Object System.Net.Sockets.UdpClient
$client.Send([System.Text.Encoding]::UTF8.GetBytes("M-SEARCH*HTTP/1.1`r`nST:upnp:rootdevice"), 37, "192.168.10.1", 1900)
[System.Text.Encoding]::UTF8.GetString($client.Receive([ref][System.Net.IPEndPoint]::New([IPAddress]::Any, 0)))
```

```yaml
HTTP/1.1 200 OK
Cache-Control: max-age=120
ST: upnp:rootdevice
USN: uuid:09182736-4554-6372-8191-c025a22a3c84::upnp:rootdevice
EXT:
Server: miniupnpd/1.0 UPnP/1.0
Location: http://192.168.10.1:52869/d030ac11.xml
```

### Linux

```bash
echo -e 'M-SEARCH*HTTP/1.1\r\nST:upnp:rootdevice' | nc -u 192.168.10.1 1900
```

```yaml
HTTP/1.1 200 OK
Cache-Control: max-age=120
ST: upnp:rootdevice
USN: uuid:09182736-4554-6372-8191-c025a22a3c84::upnp:rootdevice
EXT:
Server: miniupnpd/1.0 UPnP/1.0
Location: http://192.168.10.1:52869/d030ac11.xml
```

Locationのurlを開いて`controlURL`がエンドポイントになります。控えておいてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/986f158e-79b7-ffad-3007-cc96bcac8244.png)

`SCPDURL`を開くとリクエストのパラメータが分かります

# ポートマッピング

**192.168.10.100**はIPv4アドレス。**8000**は開放したいポート

```bash
curl http://192.168.10.1:52869/upnp/control/f96e0111 \
  -H 'SOAPAction: urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping' \
  -d '<?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:AddPortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
  <NewRemoteHost></NewRemoteHost>
  <NewExternalPort>8000</NewExternalPort>
  <NewProtocol>TCP</NewProtocol>
  <NewInternalPort>8000</NewInternalPort>
  <NewInternalClient>192.168.10.100</NewInternalClient>
  <NewEnabled>1</NewEnabled>
  <NewPortMappingDescription>Hoge</NewPortMappingDescription>
  <NewLeaseDuration>0</NewLeaseDuration>
</u:AddPortMapping>
</s:Body>
</s:Envelope>'
```

コマンド
```bash
upnpc -u http://192.168.10.1:52869/d030ac11.xml -a 192.168.10.100 8000 8000 tcp
```

### ポートマッピング確認

```bash
curl http://192.168.10.1:52869/upnp/control/f96e0111 \
  -H 'SOAPAction: urn:schemas-upnp-org:service:WANIPConnection:1#GetGenericPortMappingEntry' \
  -d '<?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:GetGenericPortMappingEntry xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
  <NewPortMappingIndex>0</NewPortMappingIndex>
</u:GetGenericPortMappingEntry>
</s:Body>
</s:Envelope>'
```

```xml
<?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:GetGenericPortMappingEntryResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
      <NewRemoteHost></NewRemoteHost>
      <NewExternalPort>8000</NewExternalPort>
      <NewProtocol>TCP</NewProtocol>
      <NewInternalPort>8000</NewInternalPort>
      <NewInternalClient>192.168.10.100</NewInternalClient>
      <NewEnabled>1</NewEnabled>
      <NewPortMappingDescription>miniupnpd</NewPortMappingDescription>
      <NewLeaseDuration>0</NewLeaseDuration>
    </u:GetGenericPortMappingEntryResponse>
  </s:Body>
</s:Envelope>
```

コマンド
```bash
upnpc -u http://192.168.10.1:52869/d030ac11.xml -l
```

### ポートマッピング削除

```bash
curl http://192.168.10.1:52869/upnp/control/f96e0111 \
  -H 'SOAPAction: urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping' \
  -d '<?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:DeletePortMapping xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1">
  <NewRemoteHost></NewRemoteHost>
  <NewExternalPort>8000</NewExternalPort>
  <NewProtocol>TCP</NewProtocol>
</u:DeletePortMapping>
</s:Body>
</s:Envelope>'
```

コマンド
```bash
upnpc -u http://192.168.10.1:52869/d030ac11.xml -d 8000 tcp
```

# グローバルIP確認

```bash
curl -X POST http://192.168.10.1:52869/upnp/control/f96e0111 -H "SOAPACTION: urn:schemas-upnp-org:service:WANIPConnection:1#GetExternalIPAddress"
```

# まとめ

curlでやるとグローバルIPが変わらないので便利です