FreeBSDでLinuxを介して802.11acなWiFiを使う

概要

FreeBSD 13.0-RELEASE がインストールされたラップトップで、802.11acな無線LANアクセスポイントに接続します。利用する無線LANデバイスは Intel Wireless-AC 8265。802.11ac(最大867Mbps)対応のカードですが、FreeBSDで提供されているドライバでは802.11a/b/g(最大54Mbps)までしかサポートされていません。

そこで、FreeBSDホストでLinux VMを用意し、無線LANカードをPCI-Passthrough接続します。Linux VM上で802.11ac接続した後、iptablesでマスカレード設定し、FreeBSDホストのデフォルトルートをVMに向けます。speedtest.netで実測したところ、Linux VMを経由させることで高速な規格でWiFi接続され、実効スループットは26Mbpsから330Mbpsへと12倍以上に高速化されました。

1. 環境情報

使用したラップトップは表に記載の通り。無線LANルータはNECのAterm WG1200HP4を用意し、802.11acで接続できるアクセスポイントを設定しました。インターネット回線は東京23区内からNURO光で接続しており、最大2Gbps出る契約です。ただし、ONU兼ルータ側のLANポート上限が1Gbpsなので、そこで律速されています。

PC ModelLenovo ThinkPad X1 Carbon 6th Gen (2018)
WiFi DeviceIntel Dual Band Wireless-AC 8265
OSFreeBSD 13.0-RELEASE
回線情報NURO光(最大2Gbps)、東京23区内

FreeBSDではiwmドライバを利用することで、上記の無線LANデバイスを使ったWiFi接続ができます。ただし、iwmのmanページを参照すると次の記載があり、サポートされている通信規格は802.11b/gまでのようです。最大54Mbps(理論値)で律速されてしまいます。

Currently, iwm only supports 802.11b and 802.11g modes. It will not associate to access points that are configured to operate only in 802.11n or 802.11ac modes.

iwm (4)

ちなみに、手元で試したところ802.11aでも接続できました。FreeBSDで直接WiFi接続する場合、この接続方法(802.11a / 5GHz帯)が最速になると思われます。他社製のWiFiカードなどを利用した場合は、もっと新しい規格で接続できるものがあるかもしれません。

2. Linuxを介したWiFi接続方法

2.1. Linux VMの用意

bhyveでUbuntu仮想マシンを作る を参考にUbuntu 20.04 Serverあたりを用意しておきます。VM側にGUIは不要ですが、お好みで用意してもOKです。

2.2. 無線LANカードをPCI-Passthroughする準備

bhyve PCI Passthrough を参考に進めます。PCI-Passthroughのためには、BIOSでVT-d(IOMMU)を有効化する必要があるので、事前に設定しておきます。FreeBSDが起動したら、PCI-Passthrough接続したい無線LANカードのbus/slot/functionを調べます。次の例では iwm0@pci0:2:0:0 になっています。2:0:0 の部分は次の設定で利用するため覚えておきます。

$ pciconf -lv
iwm0@pci0:2:0:0:	class=0x028000 rev=0x78 hdr=0x00 vendor=0x8086 device=0x24fd subvendor=0x8086 subdevice=0x0010
    vendor     = 'Intel Corporation'
    device     = 'Wireless 8265 / 8275'
    class      = network

/boot/loader.conf を開き、 pptdevs=”…” の部分を記載します(記載する数字は、先ほど調べた 2:0:0 に対応します)。FreeBSDホストで無線LAN利用していた場合は、そのための記載があると思うのでコメントアウトしておきます。

vmm_load="YES"
pptdevs="2/0/0"
#wlan_ccmp_load="YES"
#wlan_tkip_load="YES"

次に /etc/rc.conf を開き、FreeBSDホストで無線LAN利用していた場合はそのための記載がある場合はコメントアウトしておきます。

#wlans_iwm0="wlan0"
#ifconfig_wlan0="WPA DHCP"
#create_args_wlan0="country JP regdomain ETSI"
vm_enable="YES"
vm_dir="zfs:zroot/vm"

ここまで設定したらOSを再起動し、対象のPCIデバイスが ppt0 のようにpptから始まっていれば、VMへPCI-Passthrough接続する準備ができています。

$ pciconf -lv
ppt0@pci0:2:0:0:	class=0x028000 rev=0x78 hdr=0x00 vendor=0x8086 device=0x24fd subvendor=0x8086 subdevice=0x0010
    vendor     = 'Intel Corporation'
    device     = 'Wireless 8265 / 8275'
    class      = network

2.3. Linux VMに無線LANデバイスを接続する

bhyveの設定に passthru0="2/0/0" を追記します(値は上で設定したものに対応します)。

loader="uefi"
cpu=1
graphics="yes"
graphics_res="1440x900"
xhci_mouse="yes"
memory=512M
network0_type="virtio-net"
network0_switch="public"
disk0_type="virtio-blk"
disk0_name="disk0.img"
uuid="4d3641b6-9add-11eb-9d11-98fa9b19597b"
network0_mac="58:9c:fc:08:e2:fd"
passthru0="2/0/0"

この設定でVMを起動すると、対象デバイスをLinux上で確認できます。私の環境ではVMに 10.0.0.1/24 を振っているので、次のように起動してSSH接続しています。

$ sudo vm switch create public
$ sudo ifconfig vm-public inet 10.0.0.2/24
$ sudo vm start ubuntu-server
$ ssh 10.0.0.1
tnakajima@ubuntu-server:~$ lspci
00:00.0 Host bridge: Network Appliance Corporation Device 1275
00:03.0 SATA controller: Intel Corporation 82801HR/HO/HH (ICH8R/DO/DH) 6 port SATA Controller [AHCI mode]
00:04.0 SCSI storage controller: Red Hat, Inc. Virtio block device
00:05.0 Ethernet controller: Red Hat, Inc. Virtio network device
00:06.0 Network controller: Intel Corporation Wireless 8265 / 8275 (rev 78)
00:07.0 VGA compatible controller: Device fb5d:40fb
00:08.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family USB xHCI Host Controller
00:1f.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]

2.4. Linux VMからWiFi接続する

VMにログインすると、ipコマンドでWiFi接続用のデバイスが確認できます。下記の例では wlan0 となっています。

tnakajima@ubuntu-server:~$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 58:9c:fc:08:e2:fd brd ff:ff:ff:ff:ff:ff
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DORMANT group default qlen 1000
    link/ether a0:51:0b:45:1b:1d brd ff:ff:ff:ff:ff:ff

WiFiの管理は iwd がおすすめです。次の要領で使えますが、直接wpa_supplicantを叩くなどお好みの方法で接続すればOKです。

tnakajima@ubuntu-server:~$ sudo apt update
tnakajima@ubuntu-server:~$ sudo apt install iwd
tnakajima@ubuntu-server:~$ sudo systemctl start iwd
tnakajima@ubuntu-server:~$ sudo systemctl enable iwd
tnakajima@ubuntu-server:~$ sudo iwctl
[iwd]# station wlan0 scan
[iwd]# station wlan0 get-networks
[iwd]# station wlan0 connect <accesspoint name>
Passphrase: ********
[iwd]# exit
tnakajima@ubuntu-server:~$ ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=56 time=8.21 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=56 time=8.12 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=56 time=5.78 ms

--- 1.1.1.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2010ms
rtt min/avg/max/mdev = 5.781/7.370/8.212/1.124 ms

2.4. Linux VMをルータとして動作させる

Linux VMにログインしたら、 /etc/sysctl.conf の次の行をアンコメントして設定を反映します。

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
tnakajima@ubuntu-server:~$ sudo sysctl -p

次に、 /usr/local/bin/fw.sh に次のスクリプトを記載します。

#!/bin/bash

ps aux | grep '[d]hclient wlan0' >/dev/null 2>&1 || dhclient wlan0

iptables -F
iptables -t nat -F

iptables -P INPUT DROP
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -s 172.16.0.0/12 -j ACCEPT
iptables -A INPUT -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -s 169.254.0.0/16 -j ACCEPT
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

iptables -t nat -I POSTROUTING -o wlan0 -j MASQUERADE

/etc/rc.local にスクリプトのパスを記載して、起動時に実行されるようにしておきます。実行権限も設定しておきます。

#!/bin/bash

/usr/local/bin/fw.sh
tnakajima@ubuntu-server:~$ chmod +x /etc/rc.local
tnakajima@ubuntu-server:~$ chmod +x /usr/local/bin/fw.sh

ここまで設定できれば、FreeBSDのデフォルトルートをLinux VMに向ければインターネット接続されるはずです。

$ sudo route add default 10.0.0.1
$ ping -c3 1.1.1.1
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: icmp_seq=0 ttl=55 time=6.072 ms
64 bytes from 1.1.1.1: icmp_seq=1 ttl=55 time=6.014 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=55 time=12.420 ms

--- 1.1.1.1 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 6.014/8.169/12.420/3.006 ms

名前解決に問題がある場合は /etc/resolv.conf を編集してください。

nameserver 1.1.1.1

3. スループットの測定

speedtest.net にブラウザでアクセスし、実効スループットを測定した。FreeBSDホストで有線LAN接続すると930Mbps程度、FreeBSDホストから直接WiFi接続すると802.11aで26Mbps程度、Linux VMを介してWiFi接続すると802.11acで330Mbps程度の速度でそれぞれ通信できました。Linux VMを挟むことでWiFi接続速度を12倍以上に高速化できたことになります。

FreeBSDホストからの接続(有線LAN / 1Gbps)
FreeBSDホストからの接続(802.11a)
Linux仮想マシン経由での接続(802.11ac)

4. まとめ

FreeBSDでは802.11acのサポートに制約があるため、通常の方法ではWiFi接続で54Mbps以上の速度が出ません。無線LANカードをPCI-Passthrough接続したLinux VMを介して802.11ac接続することで、実効300Mbps以上のスループットが出る接続を用意できました。802.11axで接続したい場合も同様の方法が利用できると思われます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA