Android VpnService. Why does all traffic go through the TUN device? - android

I created a TUN device using VpnService. Why does the TUN interface have the highest priority among other network interfaces of my device?
Update #1
This is how I configured the TUN device:
mInterface = new Builder().setSession(getString(R.string.app_name))
.addAddress("10.0.1.1", 24)
.addRoute("0.0.0.0", 1)
.addRoute("128.0.0.0", 1)
.establish();
Update #2
This is the output of route -n without the TUN device:
shell#m0:/ $ busybox route -n
busybox route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.197.55.0 0.0.0.0 255.255.255.0 U 0 0 0 rmnet0
This is the output of route -n with the TUN device:
shell#m0:/ $ busybox route -n
busybox route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.1.0 0.0.0.0 255.255.255.0 U 0 0 0 tun0
10.197.55.0 0.0.0.0 255.255.255.0 U 0 0 0 rmnet0
shell#m0:/ $

If VpnService is enabled on Android, it does not mean that all traffic goes through VpnTunnel. This depends on IP route and allow/disable application proxy settings.
mInterface = new Builder().setSession(getString(R.string.app_name))
.addAddress("10.0.1.1", 24)
.addRoute("0.0.0.0", 1)
.addRoute("128.0.0.0", 1)
.establish();
The above code is obviously global routing, equivalent to 0.0.0.0/0, as you probably know from OpenVPN settings.
If the default gateway is tun, all IP traffic passes through the tun device.
In this case, if you don't want a socket traffic to pass through tun, you need to call VpnService::p rotect function for socket-fd to protect fd.
But that's not enough, you'll also need to find a valid network (not a VPN), call its Network::bindSocket function, and have a Socket go over that network and out.
If you don't want to protect the socket with the Network::bindSocket function! Then you can set the default network, but it is only valid for the android-process of opening the VPN service.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
try {
ConnectivityManager cm = PppVpnNetworkListener.getConnectivityManager(this._service);
if (cm != null) {
cm.bindProcessToNetwork(network);
}
} catch (Throwable ignored) {
}
}
try {
ConnectivityManager.setProcessDefaultNetwork(network);
} catch (Throwable ignored) {
}

Related

Can't ping Gateway if Access Point has no internet connection

In my app I programmatically connect to an Access Point that has no access to the internet via WifiManager and WifiConfiguration. Later on I have to access a device connected to it to read data – but I didn't get that far.
After connecting to the Wifi I'm getting my DHCP setup just fine, but if I try to ping the Gateway address by typing:
$ adb shell
OnePlus6:/ $ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
^C
--- 192.168.1.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1015ms
The gateway is unreacheable...
I suspect this has to do with the fact that Android (9?) re-routes all traffic in case of a "dead" Wifi over to mobile data – for example you can still browse the internet just fine.
You can easily replicate the issue like this:
Connect to an Access Point w/o internet access
Check if your internet still works (e.g. go to google.com)
Connect you phone via adb and ping the address of your AP
Any ideas on how to force the traffic trough Wifi, even if it's "offline"?
Edit: Output of ip route show:
OnePlus6:/ $ ip route show
10.16.52.64/29 dev rmnet_data0 proto kernel scope link src 10.16.52.67
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.116
Ok, I've found a solution. One has to bind the current process to the correct network, which can be done like this:
connectionManager = (ConnectivityManager)
context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectionManager.registerNetworkCallback(request.build(), new ConnectivityManager.NetworkCallback() {
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectionManager.bindProcessToNetwork(network);
} else {
ConnectivityManager.setProcessDefaultNetwork(network);
}
}
});

Server(AndroidWebServer) not reachable from pc

I have created AndroidWebServer on my android phone.
When I try to access 192.168.1.150:8000 (phone address) I have good response from the server. But when I try to access the same url from the pc (connected via WiFi on the same network) nothing happens.
When the server is active if I run this
adb shell netstat -at
tcp 0 0 ::ffff:127.0.0.1:8000 :::* LISTEN
That is weird because other services got foreign address
tcp 0 0 ::ffff:192.168.1.150:54 ::ffff:173.194.76.188:5 ESTABLISHED
tcp 0 0 ::ffff:192.168.1.150:36 ::ffff:31.13.92.33:http ESTABLISHED
for my service the foring address is :::*
I am not sure what I do wrong
https://github.com/lopspower/AndroidWebServer
AndroidWebServer androidWebServer = new AndroidWebServer(8000);
androidWebServer.start();
What should I change in order my phone to be accessible from my pc connected to the same WiFi network?
Thanks
Looks like your server is listening on localhost. That means it will only accept connections that originate on the local machine. Try listening on 0.0.0.0 instead; that means you accept connections from all origins.
EDIT
Change this line:
AndroidWebServer androidWebServer = new AndroidWebServer("0.0.0.0", 8000);

Android 4.2.2+ Hotspot

I hooked into the /system/bin/netd binary to log all of the commands that are sent by the Android framework when it puts up a hotspot via clicking buttons in the system settings menu. (I needed to be able to bring up the hotspot up from shell & ADB without bringing up the settings menu.)
This returned all of the commands that are used to put up the hotspot.
interface clearaddrs wlan0
interface ipv6 wlan0 disable
resolver flushif wlan0
bandwidth setglobalalert 2097152
bandwidth setglobalalert 2097152
softap fwreload wlan0 AP
softap set wlan0 asdfa wpa2-psk 12345678
softap startap
interface getcfg wlan0
interface setcfg wlan0 192.168.43.1 24 running multicast broadcast up
tether interface add wlan0
ipfwd enable
tether start 192.168.42.2 192.168.42.254 192.168.43.2 192.168.43.254 192.168.44.2 192.168.44.254 192.168.45.2 192.168.45.254 192.168.46.2 192.168.46.254 192.168.47.2 192.168.47.254 192.168.48.2 192.168.48.254
tether dns set 8.8.8.8 8.8.4.4
Seems OK.
When I issue those commands through /system/bin/ndc from shell, nothing returns an error and claims that it succeeded. Great. Fantastic. Wonderful.
200 0 Interface IP addresses cleared
200 0 IPv6 state changed
200 0 Resolver command succeeded
200 0 Bandwidth command succeeeded
200 0 Bandwidth command succeeeded
200 0 Softap operation succeeded
200 0 Softap operation succeeded
600 Iface linkstate wlan0 down
600 Iface linkstate wlan0 down
200 0 Softap operation succeeded
213 0 44:33:4c:3d:98:dc 0.0.0.0 0 down broadcast multicast
200 0 Interface configuration set
200 0 Tether operation succeeded
200 0 ipfwd operation succeeded
200 0 Tether operation succeeded
200 0 Tether operation succeeded
Super! Except for the little trivial fact that the hotspot cannot be seen afterwards and it doesn't even kick me off the wireless connection, so obviously I am missing something.
It might be useful to note that in Android 4.1.1 the following works (as expected), but in 4.2.2 it does not; I have tried endless combinations of the logged commands and the 4.1.1 commands to very little avail.
softap stopap
softap stop wlan0
softap fwreload ap0 AP
softap start wlan0
softap set wlan0 ap0 SSID wpa2-psk 12345678 11 0 8
softap startap
interface setcfg ap0 192.168.2.254 255.255.255.0 up
Here is what happens when the hotspot is taken down via the system settings menu, maybe it will be helpful:
interface getcfg wlan0
interface setcfg wlan0 0.0.0.0 0 running multicast broadcast up
tether interface remove wlan0
tether stop
ipfwd disable
softap stopap
softap fwreload wlan0 STA
softap fwreload wlan0 STA
interface getcfg wlan0
interface setcfg wlan0 0.0.0.0 0 multicast broadcast down
interface ipv6privacyextensions wlan0 enable
interface getcfg p2p0
interface setcfg p2p0 0.0.0.0 0 multicast broadcast up
interface ipv6 wlan0 enable
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
resolver flushif wlan0
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
bandwidth setglobalalert 2097152
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
bandwidth setglobalalert 2097152
This is what is logged during system startup before any user input is possible:
interface list
interface getcfg eth0
interface ipv6 wlan0 disable
interface list
bandwidth enable
softap fwreload wlan0 STA
firewall disable
interface getcfg wlan0
interface setcfg wlan0 0.0.0.0 0 multicast broadcast down
interface ipv6privacyextensions wlan0 enable
bandwidth setglobalalert 2097152
firewall disable
interface setthrottle rmnet0 -1 -1
interface getcfg p2p0
interface setcfg p2p0 0.0.0.0 0 multicast broadcast up
interface ipv6 wlan0 enable
resolver setifdns wlan0 192.168.2.254
resolver setdefaultif wlan0
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
resolver flushif wlan0
interface route add wlan0 default 192.168.2.254 32 0.0.0.0
interface route add wlan0 default 0.0.0.0 0 192.168.2.254
The only thing I do know for sure is that I can trigger the hotspot to come up in 4.4.3 when I issue commands to netd prior to the bootanimation completion.
Where did I go wrong?

Android - Ethernet - Programmatically

I am developing an Android app which will be used by custom devices which will have ethernet support (and also wifi).
The app has to enable a settings activity for Ethernet.
Please NOTE that these settings have to be run by the app and not by the Android settings, since the app will be the only thing running on the device and the user will not have access to the Android running in the background.
The user has to be able to:
ENABLE/DISABLE Ethernet
Choose DHCP or STATIC
If choosing STATIC - set IP, gateway
The problem is that I cannot access the android.net.ethernet programmatically and there is no explanation about this issue online.
So if someone has done something like this, please help me get into the right direction.
I know it is very late but it might help someone else.
I had some of the requirements you mentioned for my android application.
This is how I achieved some of the points
1. ENABLE/DISABLE Ethernet
//Enable Ethernet
ifconfig eth0 up
//Disable Ethernet
ifconfig eth0 down
3. If chosen STATIC - set IP, gateway
Fire these commands from java code.
su -c ifconfig eth0 172.19.10.105 netmask 255.255.255.0 up
route add default gw 172.19.10.2 dev eth0
You can execute these commands using following code.
Here command variable is one of the commands mentioned above.
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = reader.readLine())!= null) {
output.append(line + "n");
}
} catch (Exception e) {
e.printStackTrace();
}
String response = output.toString();

why the gateway to be bogon?

I connect my Android phone with my PC through USB. And open the usb tether option on the phone.
So, there is a new remote NDIS network adapter displayed in the PC's network connections, and there is a rnndis0 IFface on the android.
I do the following configurations:
PC: ip: 192.168.42.1 netmask: 255.255.255.0
Phone: ip 192.168.42.2 netmask: 255.255.255.0
And when ping each other, both work ok.
But when I configure the default gateway of my phone to be the address of the PC, it failed.
busybox route add default gw 192.168.42.1
busybox route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default bogon 0.0.0.0 UG 0 0 0 rndis0
192.168.42.0 * 255.255.255.0 U 0 0 0 rndis0
can anyone tell me the reason?
I believe it's marked as bogon as it is an address which should not appear in a routing table, ie a bogon route.
This is because it is a private network address. It's only a warning though.
see http://packetlife.net/blog/2009/jan/21/whats-bogon/
What is the output of
$ ip route
on Android?
SivlerZhao
Yesterday, I was unable to reproduce the problem.
Now, it reproduced.
busybox route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default bogon 0.0.0.0 UG 0 0 0 rndis0
192.168.137.0 * 255.255.255.0 U 0 0 0 rndis0
And the output of ip route is:
busybox ip route
default via 192.168.137.1 dev rndis0
192.168.137.0/24 dev rndis0 src 192.168.137.2
Actually, it works ok, but the "bogon" word apears

Categories

Resources