L-02CでLTEルータ作成

最近 Wimax のダメダメ感がすごいので、自宅のメイン回線を Plala 3M 容量無制限プランに変えました。結果、Down 4M/Up 0.2M(遅延・リセットがひどい)から Up 2〜3M/Up 1〜2M (遅延それなり) に。この速度がメインでよく耐えられるな俺。
というわけで、ArchLinux な BeagleBone Black を L-02C でルータ化した時の記録です。

L-02Cは接続が切れたあとの再接続に抜き挿しが必要と一部で言われてたりしますが、ダイアル前に以前の接続を切る(→初期化で ATH コマンドを実行する)ように設定すれば問題なくいけます。wvdialconf で設定ファイルの雛形を作った場合、この ATH による接続断が行われません。

後日追記1: ぶっちゃけ、端末にL-02Cを直結した場合と比べるとあまり速度出ません。どこが原因だろう?

後日追記2: pppインタフェースのtxqueuelenが小さすぎるのに気付いたので、設定変更方法を追加しました。マシになったような気もする程度の効果。

使ったもの

  • 本体: BeagleBone Black … ArchLinux を入れてほぼ素の状態で開始
  • モデム: L-02C … APN 登録は前もってやっておく
  • SIMカード … ドコモ系のSIM。今回は OCN モバイル One

手順

  1. 必要なソフトのインストール
  2. usb_modeswitchの設定
  3. WvDialの設定
  4. LTE接続確認
  5. IP Forwarding+IPマスカレードの設定
  6. 自動接続サービスの作成
  7. dnsmasqの設定
  8. 動作確認

1.必要なソフトのインストール

ダイアルアップを行うためのソフト (WvDial) と、L-02Cをモデムとして認識させるためのソフト (usb_modeswitch)、DNSプロキシサーバ・DHCPサーバ (dnsmasq) を使用します。以下のコマンドでインストールを行います。

$ sudo pacman -S wvdial usb_modeswitch dnsmasq

2.usb_modeswitchの設定

L-02Cの場合不要の模様で、インストールするだけでよいようです(デフォルト設定を確認してないけど、元から設定されてる?)。
usb_modeswitchをインストールしてからL-02Cを接続すると勝手にモデム(正確にはモデムとやり取りするシリアルポート)が認識されるようになります。

L-02Cの場合は ttyUSB0〜ttyUSB3 が認識され、そのうち ttyUSB2 を通信に使用します。下記のように dmesg コマンドや ls コマンドで認識されたか確認できます。

$ dmesg | grep ttyUSB
[ 5004.555644] usb 1-1.1: GSM modem (1-port) converter now attached to ttyUSB0
[ 5004.556077] usb 1-1.1: GSM modem (1-port) converter now attached to ttyUSB1
[ 5004.556498] usb 1-1.1: GSM modem (1-port) converter now attached to ttyUSB2
[ 5004.556931] usb 1-1.1: GSM modem (1-port) converter now attached to ttyUSB3

$ ls -la /dev/ttyUSB*
crw-rw---- 1 root uucp 188, 0 11月 23 11:12 /dev/ttyUSB0
crw-rw---- 1 root uucp 188, 1 11月 23 11:12 /dev/ttyUSB1
crw-rw---- 1 root uucp 188, 2 11月 23 11:16 /dev/ttyUSB2    <-- 接続時に使うのはこれ
crw-rw---- 1 root uucp 188, 3 11月 23 11:12 /dev/ttyUSB3

3.wvdialの設定

下記の内容を WvDial の設定ファイル (/etc/wvdial.conf) に書き込みます。usernameとpasswordにはプロバイダから指定されたものを設定します。

[Dialer Defaults]
Modem Type = Analog Modem
Phone = *99***1#
Carrier Check = no
Auto Reconnect = yes
Stupid Mode = yes

ISDN = 0
Init1 = ATZ
Init2 = ATH
Init3 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Dial Command = ATD
Modem = /dev/ttyUSB2
Baud = 460800

Username = <username>
Password = <password>

冒頭にも書いた通り Init2 = ATH が重要な部分で、L-02C はこれを入れておかないと2回目以降のダイアル開始を受け付けてくれません。wvdialconf コマンドで設定の雛形を出力した場合にこの初期化コマンドは入りらないので手動で追加します。

APNについては、L-02CではWindowsまたはMac上の設定ツールで前もって指定できるので、それは行われている前提としています。

4.LTE接続確認

ここまででダイアルアップの準備ができたはずなので、一度接続の確認をします。ターミナルから wvdial を実行します。

$ sudo wvdial
--> WvDial: Internet dialer version 1.61
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: ATH
ATH
OK
--> Sending: ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
OK
--> Modem initialized.
--> Sending: ATD*99***1#
--> Waiting for carrier.
ATD*99***1#
CONNECT
--> Carrier detected.  Starting PPP immediately.
--> Starting pppd at Sun Nov 23 12:04:47 2014
--> Pid of pppd: 3403
--> Using interface ppp0
--> local  IP address 153.157.38.xxx
--> remote IP address 10.64.64.64
--> primary   DNS address 222.146.35.1
--> secondary DNS address 221.184.25.1

とか表示されるので、別ウィンドウで ifconfig や ip route を実行すると ppp0 インタフェースが見えているはずです。ping 8.8.8.8 とかやって外と通信ができていることが確認できたら、Ctrl-C して WvDial を殺しておきましょう。

$ ifconfig ppp0
ppp0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 153.157.38.xx  netmask 255.255.255.255  destination 10.64.64.64
        ppp  txqueuelen 3  (Point-to-Point Protocol)
        RX packets 451  bytes 152465 (148.8 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 508  bytes 122647 (119.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

$ ip route
default dev ppp0  scope link 
10.64.64.64 dev ppp0  proto kernel  scope link  src 153.157.38.xx

$ ping -c 4 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=41 time=193 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=41 time=194 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=41 time=189 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=41 time=174 ms

--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 174.695/188.263/194.967/8.061 ms

5.IP Forwarding+IPマスカレードの設定

以下のコマンドを実行して IP パケットのフォワーディングを有効化します。

$ sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

また、Sysctlの設定ファイル (/etc/sysctl.d/30-ipforward.conf) を以下の内容で作成します。次回起動時にIPv4パケットの転送を有効にするようになります。

net.ipv4.ip_forward=1

iptablesの設定をして、eth0->ppp0 方向の IP マスカレードを有効化します(ここはちゃんと調べて自分で設定したほうが良いと思います)。

参考までに、うちの設定ファイル (/etc/iptables/iptables.rules) は以下のような感じになってます。接続はローカル (eth0) からのSSH (22/tcp)、DNS (53/udp)、DHCP (67/udp) だけ開けて、ローカル NW (192.168.1.0/24) から ppp0 方向の IP マスカレードを有効化してます。

# Generated by iptables-save v1.4.21 on Sat Jan  1 14:40:16 2000
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:LOGREJECT - [0:0]
:OPENNEW - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type any -m limit --limit 10/min -j ACCEPT
-A INPUT -m state --state NEW -j OPENNEW
-A INPUT -j DROP
-A FORWARD -i eth0 -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -j LOGREJECT
-A LOGREJECT -m limit --limit 10/min -j LOG
-A LOGREJECT -j REJECT --reject-with icmp-host-prohibited
-A OPENNEW -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A OPENNEW -i eth0 -p udp -m udp --dport 53 -j ACCEPT
-A OPENNEW -i eth0 -p udp -m udp --dport 67 -j ACCEPT
-A OPENNEW -j LOGREJECT
COMMIT
# Completed on Sat Jan  1 14:40:16 2000
# Generated by iptables-save v1.4.21 on Sat Jan  1 14:40:16 2000
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 192.168.1.0/24 -o ppp0 -j MASQUERADE
COMMIT
# Completed on Sat Jan  1 14:40:16 2000

最後に、念のため iptables サービスを有効化しておきます。

$ sudo systemctl enable iptables.service
$ sudo systemctl start iptables.service

6.自動接続サービスの作成

サービス登録用のシェルスクリプト (/usr/bin/wvdialoop) を下記の通りの内容で作成します。
WvDial を起動し、もしそのプロセスが終了したら15秒待って何度でも WvDial を呼び出しています。CLIに出るメッセージをログファイル (/var/log/wvdial) に書き出すようにしています。

#!/bin/bash
LOG='/var/log/wvdial'
(
  while : ; do
    wvdial 2>&1
    sleep 15
  done
) 2>&1 > ${LOG} < /dev/null &

上記を保存したら、以下のコマンドでシェルスクリプトに実行権限を与えます。

$ sudo chmod +x /usr/bin/wvdialoop

次にシェルスクリプトをサービスとして登録するためのファイル (/etc/systemd/system/wvdialoop.service)を作成します。

[Unit]
Description=WWAN auto-connect service
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
KillMode=none
ExecStart=/usr/bin/wvdialoop

[Install]
WantedBy=multi-user.target

上記の wvdialoop サービスを有効化します。

$ sudo systemctl enable wvdialoop.service
$ sudo systemctl start wvdialoop.service

7.dnsmasqの設定

dnsmasq の設定ファイル (/etc/dnsmasq.conf) を編集し、DNS サーバと DHCP サーバを有効にします。
(どうもこれだけ設定すれば、GW=自分、DNSサーバ=自分としてDHCPでアドレスを配布するようになる模様。よく調べてない)

resolv-file=/etc/resolv-dnsmasq.conf
interface=eth0
dhcp-range=192.168.1.101,192.168.1.150,12h
(関連するところだけ抜粋)

次に、dnsmasqが名前解決をする際にどこのサーバに聞きに行くかの設定ファイル (上で指定した /etc/resolv-dnsmasq.conf)を作成します。
ここではGoogle DNSを指定していますが、プロバイダのDNSなど聞きにいけるところを指定してください。

nameserver 8.8.8.8
nameserver 8.8.4.4

最後に、設定した dnsmasq サービスを有効化します。

$ sudo systemctl enable dnsmasq.service
$ sudo systemctl start dnsmasq.service

8.動作確認

長かったですが、これで最後。
DHCPでアドレスを貰うように設定したクライアントをネットワークにつなぎ、設定したサーバからアドレスが取得できること+外につながることを確認します。

お疲れ様でした!

追記

pppd の起動時に実行されるスクリプト/etc/ppp/ip-up.d/10-txqueuelen.sh)を以下のとおり作成します。txqueuelen に設定する値は適当に決めてください。ルータとして動作するのにデフォルトの3は少なすぎだろうと思います。

#!/bin/sh

ifconfig $1 txqueuelen 128
exit

作成したスクリプトに実行権限を付与します。ついでに現在の接続に対して txqueuelen を手動で設定しておきます。

$ sudo chmod +x /etc/ppp/ip-up.d/10-txqueuelen.sh
$ sudo ifconfig $1 txqueuelen 128

これで劇的に速度が改善するか?と言われると微妙なところです。ただ、複数台の端末がいる時の速度が若干改善したような気がします。