IIS Express を外部公開する


# 背景
Mac上の仮想環境上のWindows上でAPS.Netアプリケーションを開発しているときに

1. ゲストOS(Windows)上のIIS Expressでアプリケーションを実行
2. ホストOS(MacOS)上のブラウザで動作を確認

したいことがあります。
クライアント側のJavaScript部分をReactなどで実装している場合、Reactの開発にはOSの縛りがありません。
ホストOS上の方がファイルの編集・実行が速いので、Reactアプリケーションの

1. 編集
2. ビルド

をホストOS上でしたいです。

このために、IIS ExpressをLAN上に公開したいです。

# 環境
- Windows 10 Pro
- Visual Studio Community 2015 update2
- IIS 10.0 Express

# 手順

## 解決すべき課題
1. IIS Expressはデフォルトでlocalhost:xxxxにバインドされる。ドメイン名やIPアドレスでアクセスできない
3. Windowsは、ファイアーウォールで外部からのアクセスを禁止している
2. localhost以外にバインドしてIIS Expressを起動するには管理者権限が必要

## IIS Expressを任意のアドレスにバインド

applicationHost.configを編集する必要があります。Visual Studio 2015では

[IIS Expressでlocalhost以外のアドレスでアクセスする方法 - なか日記](http://blog.nakajix.jp/entry/2014/09/19/022536)


> プロジェクトの設定で「すべてのユーザーにサーバー設定を適用（プロジェクト ファイルに格納）」にチェックが入っている場合は、ソリューションを保存してるフォルダにある .vs （隠しフォルダ）に applicationhost.config が格納されいる

`.vs/config/applicationHost.config`を編集します。

```xml
<site name="ApiServer" id="2">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
        <virtualDirectory path="/" physicalPath="\\vmware-host\Shared Folders\shigerunakajima\slot-marketing-dashboard\ApiServer" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:56043:localhost" />
    </bindings>
</site>
```

のような定義があります。バインドしたいIPアドレス・ドメイン名を設定します。
IPアドレス`192.168.0.65`を設定したい場合は

```
<binding protocol="http" bindingInformation="*:56043:192.168.0.65" />
```

を追加します。

```
<site name="ApiServer" id="2">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
        <virtualDirectory path="/" physicalPath="\\vmware-host\Shared Folders\shigerunakajima\slot-marketing-dashboard\ApiServer" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:56043:localhost" />
        <binding protocol="http" bindingInformation="*:56043:192.168.0.65" />
    </bindings>
</site>
```

この状態で、IIS Expressを起動します。
ゲストOS（Windows）から接続すると`Bad Request - Invalid Hostname`が表示されます。

![スクリーンショット 2016-06-27 16.25.06.png](https://qiita-image-store.s3.amazonaws.com/0/15964/36a71043-4bd8-7f66-01e3-e136419ed8b7.png "スクリーンショット 2016-06-27 16.25.06.png")

回避するには **Visual Studioを管理者権限で起動** します。

## 外部からアクセス

この時点ではホストOS外部から接続するとTimeoutします。
Windowsのファイアーウォールに阻まれます。

1. Cortanaに`firewall`と入力しエンターキーを押します。
2. `操作(A)` > `新しい規則(N)...`
3. `規則の種類`に`ポート(O)`を選択
4. `次へ(N)`をクリック
5. `特定のローカルポート(S):`に`56043`を入力
4. `次へ(N)`をクリック
6. `接続を許可する(A)`を選択
7. `次へ(N)`をクリック
8. `この規則はいつ適用しますか？`はデフォルトのまま
7. `次へ(N)`をクリック
8. `名前(N):`に`iis express`を入力
9. `完了(F)`をクリック

ポートや規則の名称は好きな値に設定してください。


## 管理者権限を使わずにIIS Expressを起動
上手くいきませんでした。

[IIS Express で仮想サイトに複数のホスト名を割り当てる - しばやん雑記](http://blog.shibayan.jp/entry/20130306/1362572283)

> netsh http add urlacl を叩けば管理者権限が要らない

と言う情報があります。実際に

```
netsh http add urlacl url=http://192.168.0.65:56043/ user=Everyone
```

を実行すると、デバック実行時に`IIS Express Web サーバーを起動できません。`と、表示されるようになります。
Visual Studio を管理者権限で起動すると、IIS Expressが起動できます。

次のパターンで試しました。

```
netsh http add urlacl url=http://192.168.0.65:56043/ user=luxiar201508\shigeru.nakajima
netsh http add urlacl url=http://192.168.0.65:56043/ user=shigeru.nakajima
netsh http add urlacl url=http://192.168.0.65:56043/ user=Administrator
netsh http add urlacl url=http://192.168.0.65:56043/ user=BUILTIN\Users
netsh http add urlacl url=http://192.168.0.65:56043/ user=BUILTIN\Administrators
netsh http add urlacl url=http://+:56043/ user=everyone
```

いずれも結果は同じでした。

[Is netsh http add urlacl broken in Windows 10? - Microsoft Community](http://answers.microsoft.com/en-us/insider/forum/insider_wintp-insider_web/is-netsh-http-add-urlacl-broken-in-windows-10/ada526f6-6c65-4ff7-91d8-e6cd15d1cd14) が近いように思えます。回答はありません。

# 参考

- [Visual Studio 2015のIIS Expressにlocalhost以外からアクセスできるようにする方法 - Qiita](http://qiita.com/k_saito/items/790884389e0c0611b258)
- [IIS Express のWebサイトに他のホストからアクセスできるようにする - ASP.NETアプリケーションのデバッグ時に他のホストからのアクセスをする](https://www.ipentec.com/document/document.aspx?page=windows-iis-express-accept-outer-host-access)
- [Windows 10 ポート開放とファイヤーウォール無効及び初期化の説明](https://www.akakagemaru.info/port/windows10fw.html)
- [IIS Express サーバーを起動できませんとエラーが出た時の復旧方法 | OPC Diary](https://opcdiary.net/?p=7405)
- [IIS Expressでlocalhost以外のアドレスでアクセスする方法 - なか日記](http://blog.nakajix.jp/entry/2014/09/19/022536)
- [iis - Bad Request- Invalid Hostname while connect to localhost via wifi from mobile phone - Stack Overflow](http://stackoverflow.com/questions/22044470/bad-request-invalid-hostname-while-connect-to-localhost-via-wifi-from-mobile-ph)
- [Creating New Rules](https://technet.microsoft.com/en-us/library/cc771477(v=ws.10).aspx)
- [C# HttpListener 'Bad request' problem - Stack Overflow](http://stackoverflow.com/questions/4885057/c-sharp-httplistener-bad-request-problem)
- [iis 7 - Using Custom Domains With IIS Express - Stack Overflow](http://stackoverflow.com/questions/4709014/using-custom-domains-with-iis-express/4718029)
- [c# - IIS Express enable external request - Stack Overflow](http://stackoverflow.com/questions/3313616/iis-express-enable-external-request)
- [HttpListener と TcpListener の違いと Firewall と netsh の設定 | Moonmile Solutions Blog](http://www.moonmile.net/blog/archives/6406)