2011/04/30

Androidで逆USBテザリングを使う(NAT)

環境: Android:CyanogenMod 6.1.1, PC:Ubuntu 10.10

逆USBテザリングをブリッジ接続で行うと、不便が生じた。

- テザリングを止めるとき、PC側でブリッジ削除スクリプトを実行する必要がある。
- ブリッジ削除スクリプトを実行しないとPC側の通信ができなくなる。

それに、Androidにsshで入りたいわけでもないので、AndroidのIPアドレスがLAN内で見える必要もないし。
ということで、NATを利用する方法を考えた。この方法ならば、いつUSBを抜いてもPC側の通信には影響がない。
ブリッジ接続を紹介していたMathieuさんのコメント欄のところで、原理的に同じことを書いている人がいた。

なお、メーラーが自動受信しないとか、Android Marketのダウンロードが動作しないなどのAndroidの逆USBテザリング時に通信しないアプリが存在する理由で述べた問題があるが、私はAndroidのモジュールを変更して無理やりできるようにした。興味のある方はリンク先を参照してください。


まずPC側のIP Forwardを有効にする。

/etc/sysctl.conf:

net.ipv4.ip_forward=1


sysctl -p で反映。sysctl.confを変更せずに一時的に試すなら、
sysctl -w net.ipv4.ip_forward=1 で。

次にiptablesの設定。

iptables -A INPUT -j ACCEPT
iptables -A OUTPUT -j ACCEPT
iptables -A FORWARD -i usb0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# 一部修正 5/6

Ubuntuでiptablesの設定をOS起動時に有効にするには、自分でスクリプトを書く必要がある。私は /etc/rc.local に次のように書いている。

/etc/rc.local:

#!/bin/sh -e
/sbin/iptables-restore < /etc/iptables-rusbnat.rules


iptables-rusbnat.rules は上記の設定を行った後に iptables-save > iptables-rusbnat.rules で作った。

ここまで一度設定すれば良い。

以下はテザリングを有効にする度にPC側で実行するもの。
Android側ではやることはテザリングの設定を有効にするだけ。
停止するときはAndroidでテザリングの設定を無効にする。PC側は何もする必要がない。

rusbtether-nat:

#!/bin/sh 
set -e
export LANG=C
ROUTE=/system/bin/route
GWA=`LANG=C ifconfig usb0 | grep "inet addr:" | \
    sed 's/ *inet addr:\([0-9\.]\+\).*$/\1/'`

if [ "$GWA" = "" ]; then
    echo exit
    exit 1
fi

ping -I usb0 -c 1 $GWA > /dev/null
# add route
adb shell su -c "$ROUTE add default gw $GWA dev usb0"

DNS=`grep nameserver /etc/resolv.conf | head -n1 | awk '{print$2}'`

# clear dns
for p in net.dns1 net.dns2 net.dns3 net.rmnet0.dns1 \
    net.rmnet0.dns2 dhcp.eth0.dns1 dhcp.eth0.dns2 \
    dhcp.eth0.dns3 dhcp.eth0.dns4 net.eth0.dns1 \
    net.eth0.dns2 net.usb0.dns1 net.usb0.dns2; do
    adb shell su -c "setprop $p ''"
done

# set dns
adb shell su -c "setprop net.dns1 $DNS"

echo Completed


なお、AndroidのDNSを再設定するところはブリッジ接続の方法と変わらないので、テザリング中にWiFi/3GをONしない方が良い。
ONにした場合DNSの設定が変わって名前解決できなくなるが、再度 rusbtether-nat を実行すれば解決できるようになる。

#追記 5/3
Android側に付くアドレス 192.168.42.129 は固定のようだ。com.android.server.connectivity.Tethering にハードコーディングされていた。

1 件のコメント: