Ubuntu 16.04 / 18.04でNCXX UX302NCを自動接続する

NCXX社のUX302NCというUSBモデムでSORACOM Airを使う際，ドングルをネットワークに自動接続させる方法をまとめました．

# 環境

- デバイス: [NCXX UX302NC](https://www.ncxx.co.jp/product/ux302ncr)
- OS: Ubuntu 16.04.6 LTS および Ubuntu 18.04.3

# TL;DR

`ifup@.service` に `StopWhenUnneeded=yes` を追加し， `ExecStart` の最初に `sleep` を入れて少し待ってから `ifup` する．待つ時間は2〜3秒くらいがベストな模様．

# 設定の方法

基本的には https://soracom-files.s3.amazonaws.com/setup_air.sh が行うことをやっていけば良いですが，新しくサービスファイルを追加する必要があります．`/lib/systemd/system/ifup@.service` をベースにしますが，以下の2点変更を加えています． 

1. `StopWhenUnneeded=yes` を付ける．これを追記することで，デバイスを外したときにサービスが停止し，インターフェイスがdownされるようになります．これがないとサービスが実行したままになるため，ドングルを抜き差しした後にネットワークに自動接続しなくなります．
2. `ExecStart` の最初に `sleep 3` を追加する．デバイスのProduct IDが1034に切り替わったあとに少し待たないといけないみたいです．ちなみに，10秒は長すぎるようで，2〜3秒程度がベストなようです（理由は不明）．

また，Ubuntu 16.04と18.04では `ifup@.service` の中身が微妙に違いますが，以下の設定でいずれのUbuntuも動作することを確認しました（ベースは16.04の `ifup@.service` です）．

```conf:/lib/systemd/system/ncxx-dongle@.service
[Unit]
Description=ifup for NCXX USB Dongle (%I)
After=local-fs.target network-pre.target apparmor.service
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
DefaultDependencies=no
IgnoreOnIsolate=yes
StopWhenUnneeded=yes  # これが必要

[Service]
# avoid stopping on shutdown via stopping system-ifup.slice
Slice=system.slice
# 次の行のsleep 3が必要
ExecStart=/bin/sh -ec 'sleep 3; ifup --allow=hotplug %I; ifup --allow=auto %I; \
    if ifquery %I >/dev/null; then ifquery --state %I >/dev/null; fi'
ExecStop=/sbin/ifdown %I
RemainAfterExit=true
TimeoutStartSec=5min
```

またこれに伴い，udevのruleを変更し，デバイス接続後にどのサービスが起動されるかを変えてやる必要があります．今回は `ncxx-dongle` というサービスなので，そのように変更します． `@soracom` の部分は， `/etc/network/interfaces` で設定したインターフェイス名を使ってください（Appendix参照）．

```conf:/etc/udev/rules.d/30-soracom.rules
# UX302NC
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="11f6", ATTRS{idProduct}=="1035", RUN+="/usr/sbin/usb_modeswitch -v 11f6 -p 1035 -M '55534243123456780000000080000606f50402527000000000000000000000'"
ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="11f6", ATTRS{idProduct}=="1034", RUN+="/bin/bash -c 'modprobe option && echo 11f6 1034 > /sys/bus/usb-serial/drivers/option1/new_id'"

KERNEL=="ttyUSB*", ATTRS{../idVendor}=="11f6", ATTRS{../idProduct}=="1034", ATTRS{bNumEndpoints}=="03", ATTRS{bInterfaceNumber}=="01", SYMLINK+="modem", ENV{SYSTEMD_WANTS}="ncxx-dongle@soracom.service"
```

ドングルをPCに接続し， `systemctl status ncxx-dongle@soracom.service` を見ると，接続できたかを確認できます．

```
● ncxx-dongle@soracom.service - ifup for NCXX USB Dongle (soracom)
   Loaded: loaded (/lib/systemd/system/ncxx-dongle@.service; static; vendor preset: enabled)
   Active: active (exited) since Fri 2020-05-22 14:51:15 JST; 11min ago
  Process: 470 ExecStart=/bin/sh -ec sleep 3; ifup --allow=hotplug %I; ifup --allow=auto %I;      if ifque
 Main PID: 470 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/ncxx-dongle@soracom.service
           └─2193 /usr/sbin/pppd 460800 modem crtscts defaultroute usehostname -detach user sora noipdefau

May 22 14:51:20 lets-note pppd[2193]: pppd 2.4.7 started by root, uid 0
May 22 14:51:20 lets-note pppd[2193]: Using interface ppp0
May 22 14:51:20 lets-note pppd[2193]: Connect: ppp0 <--> /dev/ttyUSB4
May 22 14:51:20 lets-note pppd[2193]: PAP authentication succeeded
May 22 14:51:23 lets-note pppd[2193]: Could not determine remote IP address: defaulting to 10.64.64.64
May 22 14:51:23 lets-note pppd[2193]: replacing old default route to wlp58s0 [192.168.1.100]
May 22 14:51:23 lets-note pppd[2193]: local  IP address 10.128.9.123
May 22 14:51:23 lets-note pppd[2193]: remote IP address 10.64.64.64
May 22 14:51:23 lets-note pppd[2193]: primary   DNS address 100.127.0.53
May 22 14:51:23 lets-note pppd[2193]: secondary DNS address 100.127.1.53
```

# 参考

https://qiita.com/gimy/items/1d49f8e08210e9c9f20a

# Appendix

上述のセットアップスクリプトを実行すれば設定をしてくれますが，一応私が使った設定ファイルの一覧を載せます．

`wvdial` が必要なのでインストール．

```shell-session
$ sudo apt install wvdial
```

NWインターフェイスを設定． `soracom` という名前は好きに決めて良い．

```conf:/etc/network/interfaces
# ...

allow-hotplug soracom
iface soracom inet wvdial

# ...
```

UX302NCでSORACOM Airに接続した回線をデフォルトルートにしたい場合は最後の行を追加する．

```conf:/etc/ppp/peers/wvdial
noauth
name wvdial
usepeerdns
replacedefaultroute  # デフォルトルートをUX302NCにしたい場合にこれを追加
```

wvdialの設定は特に注意することなし．接続名を変える場合は [ここ](https://qiita.com/gimy/items/1d49f8e08210e9c9f20a#wvdial-%E3%81%A7%E4%BB%96%E3%81%AE%E6%8E%A5%E7%B6%9A%E5%85%88%E3%82%82%E4%BD%BF%E3%81%86%E5%A0%B4%E5%90%88)などを参考に，名前をつけた上で， `/etc/network/interfaces` の `iface` のあとに `provider その名前` を追記する．

```conf:/etc/wvdial.conf
[Dialer Defaults]
Init1 = AT+CFUN=1
Init2 = ATZ
Init3 = AT+CGDCONT=1,"IP","soracom.io"
Dial Attempts = 3
Stupid Mode = 1
Modem Type = Analog Modem
Dial Command = ATD
Stupid Mode = yes
Baud = 460800
New PPPD = yes
ISDN = 0
APN = soracom.io
Phone = *99***1#
Username = sora
Password = sora
Carrier Check = no
Auto DNS = 1
Check Def Route = 1
```