I have an HTC Desire S that has the option to connect through usb, and use the computer's internet connection. This works fine on Windows, but I'm struggling to set it up in Ubuntu. When I plug in and select internet pass-through from the usb menu, the usb1 device is created and I can ping it's ip address. I have tried various iptables configurations and setting up nat, but I'm not sure if I'm doing it right, or if there needs to be some additional configuration...

Thanks for any help.


4 Answers 4


The following works for a while, but only for the browser.

When you plug in your phone via usb and choose Internet pass-through, you should get a new RNDIS device (usb0 or usb1). For ubuntu, edit /etc/network/interfaces and add the following lines:

iface usb0 inet dhcp
iface usb1 inet dhcp

This will assign an IP automatically when the device is added. If a network address is not assigned automaticly to usb0 or usb1 you have to do it manually.

Then you need to set up NAT on your linux computer. Something like:

sudo iptables -A POSTROUTING -t nat -j MASQUERADE
sudo echo 1 > /proc/sys/net/ipv4/ip_forward 

You also need a DNS server:

sudo apt-get install bind9

This works for a few minutes, but after a while the phone gives up looking for HTC Sync and disconnects.

For rooted phones

You can connect permanently if you have a rooted phone (fre3vo worked for me). Execute the following with adb.

Enable usb mode for network and adb:

adb shell echo 6 > /sys/devices/platform/msm_hsusb/usb_function_switch

Assign an IP to the usb0 device on the phone:

adb shell ifconfig usb0 netmask up

Add a default route. The IP should be the IP assigned to usb0 in linux:

adb shell route add default gw dev usb0

Set the DNS server. This is google's open DNS server, but it can be the IP of your linux computer if you have a DNS server:

adb shell setprop net.dns1
  • 2
    According to legend, you can fake HTC sync by doing the following: On HTC phones, when you plug the usb and select internet passthrough, it waits for HTC sync and gives up. It is listening on port 6000. So you only need to fake HTC sync with netcat. Try this at the command line: phoneip=$(arp -n | grep usb | awk '{print $1}') echo -n -e "\x00\x02\x00\x00" | nc $phoneip 6000 > /dev/null The hex value of 00 02 00 00 is all it is looking for.
    – geffchang
    Commented Jun 12, 2013 at 3:27
  • @geffchang, Thanks! For windows users, when the mobile is trying to connect via the USB you can run netsh interface ip show config to see all the interface names, and then netsh interface ip show config name="Local Area Connection #2" to get just that interface, where Local Area Connection #2 is whatever the new adapter gets called. You can rename this for convenience.
    – Sam Hasler
    Commented Apr 27, 2015 at 11:54

A made this small bash to automate all. Just plug your phone in charging mode to your computer and run this bash.

/opt/android-sdk-update-manager/platform-tools/adb shell 'echo 6 > /sys/devices/platform/msm_hsusb/usb_function_switch'
sleep 1
/opt/android-sdk-update-manager/platform-tools/adb shell ifconfig usb0 netmask up
sleep 1
/opt/android-sdk-update-manager/platform-tools/adb shell setprop net.dns1

get_ip ()
ifconfig usb0 | grep inet | awk '{print $2}' | sed 's/addr://' | grep .

echo "waiting for IP on computer usb0"
while [[ `get_ip` < 192 ]];do sleep 2; done
echo "IP adress is $ip "
/opt/android-sdk-update-manager/platform-tools/adb shell route add default gw $ip dev usb0
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Since I don't have access to Linux machine myself I can't test this solution but you can try the steps described here (Google translation from Russian).

Comments to the translation:

  • "rutovanym" means rooted;
  • WB or BB means Big Brother (desktop);
  • smarta is abbreviation from "smartphone's".

Good luck!

  • Thanks, but there's an easier way than bridging the interfaces.
    – bluegray
    Commented Oct 24, 2011 at 16:12

Ok, here's exactly what I did, no rooting of HTC desired:

Setup bind9 and NAT etc...

note: 1: if you just do sudo echo 1 > /proc/sys/net/ipv4/ip_forward you will get a permissions error, so here's a script for the process 2: You can make iptables more specific about how it does things by adding parameters for specific devices.

cd ~
echo '!/bin/bash
apt-get install bind9
iptables -A POSTROUTING -t nat -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward' > setup_bind9_nat.sh

chmod +x setup_bind9_nat.sh
sudo ./setup_bind9_nat.sh

now plug in you're phone and select 'internet pass through'

wait for the device to appear in: ifconfig check it is also in: arp

I found I had to unplug the device then plug it in again for it to appear in arp, things don't work properly if arp doesn't show the device.

The device will then sit waiting for HTC Sync to send it a message so you have to mock HTC Syncs message:

#change this line to be more specific if you have more than one usb network device
get_ip ()
    arp -n | grep $phone_usb_device | awk '{print $1}'

#TODO: This needs a timeout and loop needs cleaning up, but works fine and borrowed from another post.
echo "waiting for IP on computer usb"
while [[ `get_ip` < 192 ]];do sleep 2; done
echo "IP adress is $phoneip "

echo -n -e "\x00\x02\x00\x00" | nc -q 2 $phoneip 6000 > /dev/null

I may write a version of this using D-Bus so the latter part executes automatically when the device is plugged in etc....

Ok here's my work in progress, I couldn't find anything 'generic' on d-bus so I opted for a bit of a hack solution using udev.. This isn't perfect, for instance the command gets run twice, so I'll have to see if I can filter the matching parameters a bit better, also add a timeout on the last script, just incase and see if I can replace arp with something a little better, say looking in /proc

here.s my .rules file from /etc/udev/rules.d I created

cat /etc/udev/rules.d/htc-desire.rules

You can call it anything you like but DON'T START IT WITH A NUMBER, that way it gets run last of all.

Add the following to the file as sudo using an editor of you're choice etc....

#KERNEL=="usb?" or DRIVERS=="usb" not sure which is best, may need extra mode information too from usb device.
SUBSYSTEM=="net", DRIVERS=="usb", ATTRS{manufacturer}=="HTC", ATTRS{idProduct}=="0ffe", RUN+="/home/olli/chain_mock_htc_sync.sh $kernel"

Ubuntu is setup to create the file with the correct permissions already 

ls -lrt /etc/udev/rules.d/htc-desire.rules 
-rw-r--r-- 1 root root 248 Jun 26 22:09 htc-desire.rules

Basically, if you don't see those 3 'r's,

sudo chmod a+r /etc/udev/rules.d/htc-desire.rules 

Then you'll need two further files, one to chain the other, since RUN from udev will block everything else (even though it's run last!!)...hmm... anyhow:

I created the files in my home directory for now "/home/olli/" ... so remember to replace the '/home/olli/' bit with whereever you create the files:

so for me, cd to my home directory.

cd ~

create a file called


containing the following:

/home/olli/mock_htc_sync.sh "$1" &

make it executable

chmod +x chain_mock_htc_sync.sh

create another file called


containg the following

#change this line to be more specific if you have more than one usb network device

get_ip ()
    arp -n | grep $phone_usb_device | awk '{print $1}'

#TODO: This needs a timeout and loop needs cleaning up, but works fine and borrowed from another post.
echo "waiting for IP on computer $phone_usb_device"
while [[ `get_ip`  /dev/null

Make it executable:

chmod +x mock_htc_sync.sh

Hopefully I should have a nice tidied up version soon as pos. (probably tomorrow).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .