IPv4を無効化する (FreeBSD, Ubuntu 16.04/Linux, Windows 10)

# IPv4機能の無効化はどこまでできる？

FreeBSD, Linux, Windows でIPv4無効化設定をやってみた。

散々ノウハウが流通しているIPv6の無効化ではなくて **IPv4の無効化** 。無効化にも

■プロコルスタック上での対処

- カーネルからIPv4プロトコルスタックの機能を排除して一切使わない
- IPv4プロトコルスタックは機能しているが、インターフェイスにIPv4アドレスを付与しない
- 有効なIPv4アドレスは付いているけどIPv6を優先して利用する。(デフォルトでそうなっているはずの[RFC6724](https://tools.ietf.org/html/rfc6724)のアドレス選択ポリシ)

■アプリケーション(DNSリゾルバ)の対処

- アプリ/リゾルバにA RRをクエリさせない

■DNSキャッシュサーバの対処

- (AAAAフィルタでなくて) Aフィルタ[[1]](#参考資料)する 


など、いろいろあるが、どのぐらいできそうか試してみた。

# FreeBSD 11.0-RELEASE

カーネルからIPv4プロトコルスタックを完全削除可能

Qiita掲載の記事 "[FreeBSDのsrc.conf](http://qiita.com/jj1bdx/items/3dce49fcbb1d1a2ea0ce)"から `src.conf(5)` をみて、ソースからのFreeBSD再構築時に指定できるオプションに、 `WITHOUT_INET_SUPPORT` があることに気づいた。

/etc/src.conf```
WITHOUT_INET_SUPPORT=yes
```

を書き加え、かつカーネルコンフィグ (`/usr/src/sys/amd64/conf/GENERIC`) から `options INET` を

```
options         SCHED_ULE               # ULE scheduler
options         PREEMPTION              # Enable kernel thread preemption
# options       INET                    # InterNETworking
options         INET6                   # IPv6 communications protocols
options         IPSEC                   # IP (v4/v6) security
options         TCP_OFFLOAD             # TCP offload
options         SCTP                    # Stream Control Transmission Protocol
  .
  .
```

コメントアウトしてカーネルを再構築する。

```
# cd /usr/src/sys/amd64/conf
# config GENERIC
# cd ../compile/GENERIC
# make cleandepend
# make depend
# make
# make install
```

作り直したカーネルで再起動すると、lo0インターフェイスから127.0.0.1が消え、socket(AF_INET,...) システムコールを呼んでも、errno = EPROTONOSUPPORT が返ってくる。IPv4スタックがカーネルからきれいに消えてくれて気持ちよい。

ちなみに、デフォルトで起動する sendmail_submit が標準設定だとローカルホスト(127.0.0.1)を指すので、

```
Starting sendmail_submit.
554 5.3.0 host "localhost" unknown: Address family not supported by protocol family 
```

を吐いて立ち上がらなかったが、 `/etc/mail/freebsd.submit.mc` を見ると

```
dnl If you use IPv6 only, change [127.0.0.1] to [IPv6:::1]
FEATURE(`msp', `[127.0.0.1]')dnl
```
と書いてあり、IPv6 onlyで使うことも考慮はされていた。

## ipfw が使えなくなる (2017.1.12追記) 

IPv４のコードに強く依存しているようで、ipfwが利用不可となる。フィルタリングの他、ユーザランド動くpppd, natdなどのためのdivert, altq, dummynet などが影響を受ける。代替手段としてはpfは使える様子。

# Ubuntu 16.04 LTS (Linuxカーネル3.3.0)

カーネルからIPv4機能を削除できなかった。

カーネルコンフィグの依存関係は

```
TCP/IP Networking [*]
 --> The IPv6 protocol <*>
```

の従属の関係になっていて、TCP/IP Networking (=IPv4)を丸ごと外すことができるが、IPv6も外れてしまう。IPv6を活かしつつ、IPv4だけを消し去ることは簡単ではないようだ。

ちなみにIPv6の無効化は```
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6
echo 1 > /proc/sys/net/ipv6/conf/default/disable_ipv6
```
とか、RHEL/CentOS系ならipv6モジュールロードの無効化、grubオプションでの無効化などいろいろ方法があるのだが、どれもそれに相当するIPv4無効化設定が見当たらない。

カーネルからIPv4スタックの機能を排除できなかったが、ループバックアドレス以外のIPv4アドレスは付与しないことでIPv4無効化相当の効果は得られるし、デフォルト動作でIPv6が優先されるのでおそらく問題は出ないと思う。ループバックインターフェイス inet 127.0.0.1/8 の付与が残ってしまったり、ping 127.0.0.1 は機能してしまう点など残骸を気持ち悪いと感じかもしれないが (ループバックアドレスは `ip addr del 127.0.0.1/8 dev lo` で消すのもあり)。

# Windows 10

```
C:\>netsh interface ipv4 uninstall
```

管理者権限でuninstallして再起動するとIPv4スタックが機能しなくなった。Loopback Pseude-Interface-1 の 127.0.0.1 も機能してないし、ipconfig の出力からもIPv4アドレスに関する情報が全て消えてくれる。

```
C:\>ping 127.0.0.1
IP ドライバーにアクセスできません。一般エラーです。

C:\>ping ::1
::1 に ping を送信しています 32 バイトのデータ:
::1 からの応答: 時間 <1ms
::1 からの応答: 時間 <1ms
::1 からの応答: 時間 <1ms
 .
 .
```
と期待した動作となる。

一方、ネットワークアダプタのプロパティを開いて、アダプタにバインドしたプロトコルの

- [ ] インターネット プロトコル バージョン4 (TCP/IPv4)
- [x] インターネット プロトコル バージョン6 (TCP/IPv6)

IPv4のチェックを設定を外す方法だけでは、そのアダプタにIPv4アドレスがつかなくなって、ipconfigの出力からもIPv4アドレスが消えてくれる。実効上無効化できたことと等しいが、Loopback Pseude-Interface (127.0.0.1) は生き続けて通信はできるので、プロトコルスタックとしての機能は生き続けたままである。127.0.0.1 は

```
netsh interface ipv4 delete address interface="Loopback*" address=127.0.0.1
```
でアドレスを消すことはできる。

# おしまいに

ほとんどの場合IPv6が優先されるので、古い実装(IPv4)があっても有害となることは無いと思う。。なのでIPv4が廃れても、当分の間は実装されたまま放置の気がする。そのうち

- やっぱり古い実装(IPv4)は有害だ!と言う場面が現れ、"IPv4 無効化" ワードが検索が流行り始めたり

- 害はなくても `127.0.0.1` を見て「なんだこの変な数字は?!」とIPアドレスと認識できない世代が現れる一方、年寄りが「このアドレスなつかし～」と言い出したり。

そんな時代が来ればいいと思う。


# 参考資料

[1] [WIDEプロジェクト, Live with IPv6 Working Group 2012 年度活動報告]
(http://member.wide.ad.jp/tr/wide-tr-live-with-ipv6-wg-report-2012-01.pdf)