【Windows 10】非Server EditionでDHCPサーバを構築する【DHCP】

# はじめに
最近、Windows 10 Proにアップグレードしたことに伴い、Hyper-Vを使い始めました。
Hyper-Vの仮想ネットワークを作り、その中でDHCPサーバを稼働させる必要があったので、構築しました。

DHCPサーバ候補としていくつかありましたが、管理のしやすさから、Open DHCP Serverを使うことにしました。

Open DHCP Server
http://dhcpserver.sourceforge.net/


# TL;DR
- Open DHCP Serverをインストールし、Serviceとして実行させる
- Windows Firewallの設定をする

# 環境
以下の環境で動作確認しました。
下記記事で記載した環境と同一です。

[【Windows】Docker Desktop for WindowsとVagrant+Hyper-V環境を共存させる #1/3 - Qiita](https://qiita.com/tmiki/items/bdc7ff43b3d8d636ec8f)

- OS: Windows 10 Pro 10.0.17763 Build 17763
- GitBash 2.21.0
- Vagrant 2.2.4
- Hyper-V仮想ネットワーク・仮想スイッチ:
    - 名称: Hyper-V Internal with WinNAT
    - WinNAT設定済み
    - IPアドレスレンジ: 192.168.254.0/23
    - ホストNICのIPアドレス: 192.168.254.1/23（※VMから見た場合、デフォルトゲートウェイになる）

# 手順
## Open DHCP Serverのインストール
公式サイトをたどり、ファイルをダウンロードします。2019/3/22現在の最新版は、1.73です。
Sourceforge.netから配布しているようです。
[Open DHCP Server](http://dhcpserver.sourceforge.net/)

実行形式になっているので、適切なパスを指定して展開＆インストールします。
私は「C:\opt\OpenDHCPServer」にインストールしました。

## Open DHCP Serverを設定する
インストールされたフォルダに「OpenDHCPServer.ini」というファイルがあるので、これを開いて下記のように設定します。
オリジナルファイルは、コメントでいろいろと説明が書いてありますので、バックアップを取っておくと良いでしょう。

```ini:OpenDHCPServer.ini
[LISTEN_ON]
192.168.254.1

[LOGGING]
LogLevel=Normal

[RANGE_SET]
DHCPRange=192.168.255.1-192.168.255.254
SubnetMask=255.255.254.0
DomainServer=8.8.8.8, 8.8.4.4
Router=192.168.254.1

[HTTP_INTERFACE]
HTTPServer=192.168.254.1:6789

[GLOBAL_OPTIONS]

```

DHCPサーバとしての動作は[RANGE_SET]というセクションに書きます。上記設定内容を整理すると下記のようになります。

- DHCPサーバとしてListenするIPアドレスは「192.168.254.1」とする
- DHCPクライアントに割り当てるIPアドレスは、「192.168.255.1」から「192.168.255.254」までの範囲とする
- DNSサーバとして8.8.8.8, 8.8.4.4を指定する
- デフォルトゲートウェイとして192.168.254.1を設定する

[HTTP_INTERFACE]というセクションを設定することで、WebブラウザからDHCPサーバの稼働状況を確認できるようになります。


## Open DHCP Serverを再起動する
Open DHCP ServerはWindowsのServiceとして稼働しているので、一般的なServiceと同じように再起動ができます。

まず、スタートメニューから「services.msc」と入力して、Serivces管理ツールを開きます。
「Open DHCP Server」というServiceがあるのでこれを探し、ダブルクリックして開きます。
![RestartOpenDHCPServer_01.png](https://qiita-image-store.s3.amazonaws.com/0/137777/521b8b05-924a-a3b9-1e95-9b1bef93fc94.png)


「Stop」ボタンを押して、一旦サービスを停止させます。完了するまで数秒～数十秒かかります。
![RestartOpenDHCPServer_02.png](https://qiita-image-store.s3.amazonaws.com/0/137777/b03e30ad-69f5-b4aa-244e-cf0f7c2907fe.png)

「Start」ボタンを押して、サービスを開始させます。
![RestartOpenDHCPServer_03.png](https://qiita-image-store.s3.amazonaws.com/0/137777/55fbe94d-d4cb-5801-4a39-6a6eb3e2a4b5.png)

## Windows Defender Firewallで、Open DHCP Serverへの許可設定をおこなう
Open DHCP Serverのインストーラは、Serviceとしての設定は行っても、Firewallの設定まではおこなってくれません。手動で設定を追加する必要があります。

まず、コントロールパネルから、Windows Defender Firewallを開き、「Advanced settings」を開きます。
![WindowsDefenderFirewall_01.png](https://qiita-image-store.s3.amazonaws.com/0/137777/e4475d53-941e-a923-fd44-7a85fe00158f.png)

左ペインから「Inbound Rules」を開いたのち、右ペインの「New Rule...」をクリックします。
![WindowsDefenderFirewall_02.png](https://qiita-image-store.s3.amazonaws.com/0/137777/b5925a04-6294-3452-fc5c-71ccd9e87c1f.png)

設定用のポップアップウィンドウが開くので、指示に従って設定していきます。
まずRule TypeはProgramを指定します。DHCPサーバは特にPortやProtocolの指定が難しいので、Programで設定するのが無難です。
![WindowsDefenderFirewall_03.png](https://qiita-image-store.s3.amazonaws.com/0/137777/25046726-eaf2-ad8e-12b9-f69f8ec11285.png)

実行プログラムのパスを指定します。先ほどインストールしたフォルダの「OpenDHCPServer.exe」を指定します。
![WindowsDefenderFirewall_04.png](https://qiita-image-store.s3.amazonaws.com/0/137777/b50cbde5-9340-5c3c-9f8c-924bbe984ef8.png)

Actionは「Allow the connection」を指定します。これで上記で指定したプログラムに対する通信が許可されます。
![WindowsDefenderFirewall_05.png](https://qiita-image-store.s3.amazonaws.com/0/137777/012019c8-0fde-c414-4239-abb685169014.png)

Profileはすべてチェックした状態にします。通信しているネットワークの接続プロファイルにより、許可／拒否の設定ができます。
![WindowsDefenderFirewall_06.png](https://qiita-image-store.s3.amazonaws.com/0/137777/669f2c07-d449-a153-3dfd-de02a24dc213.png)

Nameは任意のものを指定してください。ここでは「OpenDHCPServer」としました。
最後にFinishボタンを押すと、Ruleの作成が完了します。
![WindowsDefenderFirewall_07.png](https://qiita-image-store.s3.amazonaws.com/0/137777/445bd250-72a8-ea66-55dc-ab3842ae0274.png)

Inbound Rulesに、先ほど作成したRuleが表示されていることを確認します。
![WindowsDefenderFirewall_08.png](https://qiita-image-store.s3.amazonaws.com/0/137777/a2c1a867-543f-431b-4975-7c1df24f7d7d.png)

これでWindows Defender Firewallの設定は完了です。

## 新たな仮想マシンを実行し、DHCPサーバの動作を確認する
それでは、DHCPサーバが意図したとおりに動くかどうか確認していきます。
当該ネットワークに新たにVMを作り、動作確認するのが簡単です。下記のようなVagrantfileを作り、vagrant upを実行します。
なお、Hyper-Vを利用する場合、vagrant upを実行するにはAdministrator権限が必要となります。

```:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "Yojimbo108/AmazonLinux2"
 
  config.vm.provider "hyperv" do |v|
    v.memory = 1024
    v.cpus = 1
  end

  config.vm.define :"stdsv4" do |c1|
    c1.vm.hostname = "stdsv4"
  end

end
```

vagrant upを実行します。Hyper-Vに2つ以上の仮想ネットワークがある場合、どちらにするか聞いてきますので、指定します。
またデフォルトで、ゲストVMからホストOSのフォルダをSMBマウントしようとするため、ホストOSのアカウントを聞いてきます。

```:vagrant&nbsp;up
Bringing machine 'stdsv4' up with 'hyperv' provider...
==> stdsv4: Verifying Hyper-V is enabled...
==> stdsv4: Verifying Hyper-V is accessible...
==> stdsv4: Importing a Hyper-V instance
    stdsv4: Creating and registering the VM...
    stdsv4: Successfully imported VM
    stdsv4: Please choose a switch to attach to your Hyper-V instance.
    stdsv4: If none of these are appropriate, please open the Hyper-V manager
    stdsv4: to create a new virtual switch.
    stdsv4:
    stdsv4: 1) DockerNAT
    stdsv4: 2) Hyper-V Internal with WinNAT
    stdsv4:
    stdsv4: What switch would you like to use? 2
    stdsv4: Configuring the VM...
==> stdsv4: Starting the machine...
==> stdsv4: Waiting for the machine to report its IP address...
    stdsv4: Timeout: 120 seconds
    stdsv4: IP: 192.168.255.2
==> stdsv4: Waiting for machine to boot. This may take a few minutes...
    stdsv4: SSH address: 192.168.255.2:22
    stdsv4: SSH username: vagrant
    stdsv4: SSH auth method: private key
    stdsv4:
    stdsv4: Vagrant insecure key detected. Vagrant will automatically replace
    stdsv4: this with a newly generated keypair for better security.
    stdsv4:
    stdsv4: Inserting generated public key within guest...
    stdsv4: Removing insecure key from the guest if it's present...
    stdsv4: Key inserted! Disconnecting and reconnecting using new SSH key...
==> stdsv4: Machine booted and ready!
==> stdsv4: Preparing SMB shared folders...
    stdsv4: You will be asked for the username and password to use for the SMB
    stdsv4: folders shortly. Please use the proper username/password of your
    stdsv4: account.
    stdsv4:
    stdsv4: Username: ****
    stdsv4: Password (will be hidden):
Error! Your console doesn't support hiding input. We'll ask for
input again below, but we WILL NOT be able to hide input. If this
is a problem for you, ctrl-C to exit and fix your stdin.
     stdsv4: Password (will be hidden): ********

Vagrant requires administrator access to create SMB shares and
may request access to complete setup of configured shares.
==> stdsv4: Setting hostname...
==> stdsv4: Mounting SMB shared folders...
    stdsv4: D:/Dev/git/server-config/vagrant_amazonlinux2_hyperv_dhcp => /vagrant
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t cifs -o vers=2.0,credentials=/etc/smb_creds_vgt-5107fd8e59246ad3b9a29689ca11bbd0-6ad5fdbcbf2eaa93bd62f92333a2e6e5,uid=1000,gid=1001 //10.1.1.34/vgt-5107fd8e59246ad3b9a29689ca11bbd0-6ad5fdbcbf2eaa93bd62f92333a2e6e5 /vagrant

The error output from the last command was:

mount: /vagrant: bad option; for several filesystems (e.g. nfs, cifs) you might need a /sbin/mount.<type> helper program.

```

SMBのマウントに失敗しましたが、DHCPでのIPv4の設定は成功しているはずです。vagrant sshして設定を確認します。

```:vagrant&nbsp;ssh
$ vagrant ssh
Last login: Fri Mar  1 15:21:31 2019

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
4 package(s) needed for security, out of 5 available
Run "sudo yum update" to apply all updates.
[vagrant@stdsv4 ~]$ 
```

DHCPサーバとして指定したIPアドレスレンジ内のアドレスが付与されてています。

```:ifconfig
[vagrant@stdsv4 ~]$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.255.2  netmask 255.255.254.0  broadcast 192.168.255.255
        inet6 fe80::215:5dff:fe14:2515  prefixlen 64  scopeid 0x20<link>
        ether 00:15:5d:14:25:15  txqueuelen 1000  (Ethernet)
        RX packets 41965  bytes 55059083 (52.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9088  bytes 704092 (687.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

デフォルトゲートウェイも、DHCPサーバで指定したものとなっています。

```:netstat&nbsp;-rn
[vagrant@stdsv4 ~]$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.254.1   0.0.0.0         UG        0 0          0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U         0 0          0 eth0
192.168.254.0   0.0.0.0         255.255.254.0   U         0 0          0 eth0
```

DNSサーバも、DHCPサーバで指定したものとなっています。

```:/etc/resolv.conf
[vagrant@stdsv4 ~]$ cat /etc/resolv.conf
; generated by /usr/sbin/dhclient-script
nameserver 8.8.8.8
nameserver 8.8.4.4
```

## Open DHCP Serverの稼働状況を確認する
Open DHCP Serverの設定ファイルで[HTTP_INTERFACE]を設定した場合、Webブラウザから稼働状況を確認することができます。
今回は、下記のURLでHTTPアクセスできるようにしました。

実際に下記URLにアクセスしてみます。
http://192.168.254.1:6789/

下記のようにDHCPのリース状況が確認できます。
![2019-03-22_02h52_19.png](https://qiita-image-store.s3.amazonaws.com/0/137777/abcbcf8e-e5fd-30ac-e690-514e83836726.png)

# 補足：特定のMACアドレスに対して特定のIPアドレスを付与する
基本的にはDHCPを利用した場合、IPアドレスは空いているものから割り当てられ、固定することができません。しかしながら、多くのDHCPサーバは、特定のMACアドレスに対して特定のIPアドレスを付与する、という機能を持っており、Open DHCP Serverもまた同様です。
Open DHCP Serverの設定ファイルに下記のような設定を追加することで、これを実現できます。
この例では、MACアドレスが「00:15:5d:14:25:16」であればIPアドレスとして「192.168.255.201」を付与する、という設定になります。

```ini:OpenDHCPServer.ini
[00:15:5d:14:25:16]
IP=192.168.255.201
```

ではこの機能を使って、Vagrantで起動するVMインスタンスに固定でIPアドレスを付与できるかというと、現状ではできません。
対象のVMのNICにMACアドレスを指定する必要がありますが、現在のVagrantではHyper-Vのネットワークに関する機能は持っておらず、Vagrantfile内で指定することができません。
仮に下記のように設定したとしても無視されます。vagrant up実行時にはエラー等は出力されません。

```:Vagrantfile
  config.vm.define :"stdsv4" do |c1|
    c1.vm.hostname = "stdsv4"
    c1.vm.network "private_network", mac: "00155d142516" # ←この設定は無視される。
  end
```

# 関連記事
[【Windows】Docker Desktop for WindowsとVagrant+Hyper-V環境を共存させる #1/3 - Qiita](https://qiita.com/tmiki/items/bdc7ff43b3d8d636ec8f)
[【Windows】Docker Desktop for WindowsとVagrant+Hyper-V環境を共存させる #2/3 - Qiita](https://qiita.com/tmiki/items/d5c63a2ca0573e01b321)
[【Windows】Docker Desktop for WindowsとVagrant+Hyper-V環境を共存させる #3/3 - Qiita](https://qiita.com/tmiki/items/1d5edb4e482f0f38bfd2)　←ここで必要になる

# おわりに
Hyper-Vの「Default Switch」がちゃんと安定して動くまでは、個別にDHCPサーバの構築が必要になるでしょう。
面倒ですが、「Default Switch」が安定するまでの辛抱です。