三行で説明すると
- hostapd 起動して
- DHCP サーバ立てて
- iptables でパケット転送する
環境
使ったマシンは、ThinkPad0T430s。
OS version は、Ubuntu 12.04。
wlan0
で端末から接続受けて、eth0
でインターネットに流す。
hostapd の設定
hostpad をインストール。
sudo apt-get install hostapd
設定ファイルのテンプレがここにあるみたい。
/usr/share/doc/hostapd/examples/hostapd.conf.gz
こいつをありがたくいただく。
sudo zcat /usr/share/doc/hostapd/examples/hostapd.conf.gz > /etc/hostapd/hostapd.conf
続いて、/etc/hostapd/hostapd.conf
を編集。修正したのは、これらの項目。
ssid/passphrase あたりはお好みで。
driver=nl80211
ssid=test-ubuntu
hw_mode=g
channel=1
wpa=2
wpa_passphrase=testubuntu
軽く動作確認。
$ sudo hostapd /etc/hostapd/hostapd.conf
Configuration file: /etc/hostapd/hostapd.conf
Failed to update rate sets in kernel module
Using interface wlan0 with hwaddr 84:3a:4b:20:b9:40 and ssid 'test-ubuntu'
この状態で、別の端末で無線アクセスポイントの一覧眺めて、test-ubuntu
が見えてれば OK。
基本デーモンとして動かす予定なので、/etc/default/hostapd
に設定ファイルのパスを追加しておく。
DAEMON_CONF="/etch/hostapd/hostapd.conf"
で、hostapd
起動しておく。
$ sudo service hostapd restart
* Stopping advanced IEEE 802.11 management hostapd [ OK ]
* Starting advanced IEEE 802.11 management hostapd [ OK ]
$ ps aux | grep hostapd | grep -v grep
root 7212 0.5 0.0 33468 1220 ? Ss 18:14 0:00 /usr/sbin/hostapd -B -P /var/run/hostapd.pid /etc/hostapd/hostapd.conf
DHCP の設定
DHCP サーバをインストール。isc-dhcp-server
を採用。
sudo apt-get install isc-dhcp-server
/etc/dhcp/dhcpd.conf
の末尾に、繋ぎにきた端末に払い出す IP アドレスのリース情報を追記。
IP 体系はお好みで。既存の NW 構成とバッティングしない程度に気を配って。
subnet 192.168.126.0 netmask 255.255.255.0 {
range 192.168.126.10 192.168.126.254;
option domain-name-servers 8.8.8.8;
option routers 192.168.126.1;
default-lease-time 600;
max-lease-time 7200;
}
hostapd
同様、デーモンで動かすので、/etc/default/isc-dhcp-server
に使用するインタフェースを追加。
INTERFACES="wlan0"
wlan0
に、DHCP 設定と矛盾無いように IP アドレスを設定。
$ sudo ifconfig wlan0 192.168.126.1 netmask 255.255.255.0
で、dhcpd
起動しておく。
$ sudo service isc-dhcp-server restart
stop: Unknown instance:
isc-dhcp-server start/running, process 7225
$ ps aux | grep dhcpd | grep -v grep
dhcpd 7225 0.0 0.0 18808 4512 ? Ss 18:14 0:00 /usr/sbin/dhcpd -f -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf wlan0
iptables の設定
net.ipv4.ip_forward
という IP フォワーディングのカーネルパラメータがあるので、こいつを有効にする。
$ sudo sysctl -w net.ipv4.ip_forward=1
端末から受信した wlan0
宛のパケットを、eth0
に流してやる。
NAT テーブルに追加。
$ sudo iptables -t nat -A POSTROUTING -s 192.168.126.0/24 -o eth0 -j MASQUERADE
NAT テーブル確認すると、こんな感じ。
$ sudo iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.126.0/24 anywhere
以上で、無線 LAN ルータ完成。
ちなみに、NAT テーブルから上記ルールを削除するときは -D
で。
$ sudo iptables -t nat -D POSTROUTING -s 192.168.126.0/24 -o eth0 -j MASQUERADE
エラー事例
nl80211 driver initialization failed.
無線デバイス (wlan0) を有効にしていなかったので、有効にしたら解決。
$ sudo hostapd /etc/hostapd/hostapd.conf
Configuration file: /etc/hostapd/hostapd.conf
Could not set interface mon.wlan0 flags: Operation not possible due to RF-kill
nl80211: Failed to set interface wlan0 into AP mode
nl80211 driver initialization failed.
rmdir[ctrl_interface]: No such file or directory
ELOOP: remaining socket: sock=4 eloop_data=0xfe81f0 user_data=0xfeb0a0 handler=0x4339e0
ELOOP: remaining socket: sock=6 eloop_data=0xfed870 user_data=(nil) handler=0x43ce30
wlan0: IEEE 802.11 Hardware does not support configured channel
デフォで hostapd.conf
に設定されている hw_mode と channel が、このマシンだとダメっぽい。
hw_mode=a
(IEEE 802.11a) を hw_mode=g
(IEEE 802.11g) に変更。
あわせて、channel=60
を channel=1
に変更。
$ sudo hostapd /etc/hostapd/hostapd.conf
Configuration file: /etc/hostapd/hostapd.conf
wlan0: IEEE 802.11 Configured channel (60) not found from the channel list of current mode (2) IEEE 802.11a
wlan0: IEEE 802.11 Hardware does not support configured channel
Could not select hw_mode and channel. (-1)
wlan0: Unable to setup interface.
rmdir[ctrl_interface]: No such file or directory
DHCP でうまく IP アドレスが払い出されない
自分の場合だと、端末側は DHCP Discover
を送信するも、Ubuntu 側の wlan0
でそれを受信できていないってケースが。
他の無線 LAN とバッティングしてよからぬ状況になってるかな、ってことで、使用するチャンネルを変更したら解決した。
channel=1
の部分を channel=11
とか、少しズラしてあげるといいんじゃないかなと。