I'm working on programmatically setting a VPN connection on android devices. I was successfully able to do so for devices using OS 2.3.5 and before (I used reflection to get to the hidden classes). But with android 4.0 they got rid of the old classes and use the VPNService class instead.
I figured the best place to start would be to use the ToyVPN example android provided, but I'm facing a lot of challenges with it. In the example code they only needed to send the server address:
InetSocketAddress server = new InetSocketAddress(mServerAddress, Integer.parseInt(mServerPort));
And then created the VPN tunnel by opening the channel:
tunnel = DatagramChannel.open();
But in my case I need to send the server address, username and password. So far I haven't figured out how to do so. My best guess was to do something like this:
Authenticator.setDefault(new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("user","pass".toCharArray());
}});
try {
// Create a DatagramChannel as the VPN tunnel.
tunnel = DatagramChannel.open();
But this did not work.
so what I'm asking is:
Is there a way, other than what's used in ToyVpn, to create a VPN connection programmatically?
If not, how do I send the credentials when I want to establish a connection to the server?
Edit
I forgot to mention that I need to specify the VPN type (PPTP, L2TP, L2TP/IPSec PSK or L2TP/IPSec CRT).
Basically the VPN API introduced in Android 4.0+ only allows you to implement your own VPN implementation. It does no more than opening the Linux TUN device and pass the file descriptor to you, plus setting up the routes/DNS servers/etc you provided. The whole VPN protocol implementation is solely up to you.
So the short answer is: no. you can't use the VPN API to set up any of the
PPTP, L2TP, L2TP/IPSec PSK or L2TP/IPSec CRT
VPN connections, unless you roll out your own implementation of the mentioned VPN types.
That being said, you may still try to broadcast an Intent to bring your user to the system VPN settings activity and ask them to manually configure/start the VPN.
Oh and one more thing to add. At the time of this writing, Android's latest DevicePolicyManager (API level 21) already provides WiFi settings provisioning support. I would personally guess that Google might continue to add more Android for Work features, which may include VPN provisioning support you need. I/O 2015 is only a few days away so let's wait and see...
There is a way to set a VPN connection programmatically. You might want to take a look at OpenVPN for Android (ics-openvpn) project's source. If there is no need for your app to make the connection directly, you can also use intents to trigger a connection from ics-openvpn. OpenVPN offers a wide range of settings, but you still have to see if it is compatible with your server.
The VpnService class introduced in Android 4.0 (ICS) can only do some settings such as the creating the network interface (only tun mode), some routes and DNS servers. It is still needed for your app to be able to connect without root permission. You might want to check here for more info on how to use VpnService.
As far as I have explored ics-openvpn's code, the app integrates a OpenVPN binary runnable in the app's APK. The app executes this binary, sending and receiving commands through a local socket. The binary takes care of almost everything, you just have to parse the input to know what methods of VpnService.Builder you will be calling, and what information will you be sending back through the socket (this includes confirmations, config files, credentials, bytecounts, etc)
Related
There are many answers on SO already claiming that you cannot programmatically configure a VPN profile on Android device. The VpnService API from Android only allows usage of VPN in your own app, and there is no other API available.
The how do apps like OpenVPN for Android etc. achieve that? I can configure profile through the OpenVPN app and other apps will be able to use this connection.
You are misunderstanding the nature and purpose of the handle/file descriptor returned by VpnService.Builder's establish() method. You might want to read the API description again.
The gist of it is that it's a file descriptor for a TUN device to which Android directs network traffic from other apps via policy routing (affected apps/traffic can be controlled through the methods of the builder). The app can then use the file descriptor to read the packets sent by other apps and e.g. forward them through a VPN connection (using a regular UDP/TCP socket). Returning traffic from a VPN connection can likewise be re-injected into the system by writing to the file descriptor of the TUN device.
The use case is that:
all the applications on the android phone would connect to internet through a wifi.
And I want to have an application that eavesdrops on the http traffic from all apps so that I can find what sites they visit.
This application would be distributed as an apk and users would install this app on their phone.
How do I achieve this ?
I will tell what I tried:
Used a Custom Vpn Service application where an activity triggers a service derived from VpnService.
The Custom VpnService calls builder and sets Mtu, addRoute, addAddress, and then addDnsServer.
Then the service reads from the file descriptor associated with the interface generated from builder's establish() call.
Now if the addRoute is called with ("0.0.0.0", 0), Iam able to intercept the traffic and see packet contents. But Iam not able to route the packets without creating udp tunnel to an external server which I dont want to do.
If the addRoute is called with the Wifi router IP, then routing automatically happens for all packets generated. But I am not able to intercept the packets on the file descriptor associated with the virtual interface. It simply doesnt receive any data on read() call.
What I want to do is:
intercept the traffic to inspect the http headers
at the same time, do routing as usual like a normal wifi connection does.
Have everything self contained in the phone. There should be no external server.
this appliction should not require any rooting or such. It should install the way a normal app does.
I would suggest 1) setting a proxy and 2) running an app which acts as one. The combination of these two won't require root privileges.
SETTING THE PROXY
This first point is probably the most tricky one. The only way of setting a software-level proxy (without requiring root) is by navigating to the Wi-Fi connection settings and manually set the proxy. However, there is an open-source application that can eventually bypass this particular step: ProxySettings.
INTERCEPTING THE TRAFFIC
In my opinion, your best bet is using SandroProxy, an open-source proxy application for Android. It is extremely well written, currently maintained and supported, and will allow you to intercept the HTTP traffic and even modify it. The code can be found here, while the example application can be found here.
This solution should fulfil all of your requirements:
Intercept the traffic (even edit it): thanks to the proxy setting, all the network traffic goes through the proxy address, which corresponds to your application
Edit is optional: everything will keep working as no proxy is set
Everything is local: no need for external servers, your proxy is the installed application
No root is required
I have implemented an Android application which connects to its application server via a VPN tunnel. Thats fine.
However I want that the application turn on the Android VPN service itself ,rather than I am turning on the VPN on Android manually.
Is it possible to turn on this from java source code, like
// TO DO
if (something) {
VPN ON
}
Currently it's not possible to do that. Event with the latest classes in Android 4.0, User action is required to create a VPN connection. It's considered a security issue to be able progrmmatically to establish vpn connection (e.g. without the user to notice).
It is not possible to turn off the VPN from Java source code, unless the device is rooted, then there some hacks around. (so I have been told being an Android developer for a major software company) It is almost possible to do but it will take writing something in Native Code. There are some companies that are currently attempting to do this in an SDK. Authentec is one, but even in there SDK it is not possible to shut off the VPN connection yet. I came here looking to see if anyone has done this before but I know it is not possible through Java code, it will have to be in Native Code ( C for simpletons like myself)
Just a quick question as Google isn't throwing up much.
Is it possible to create a VPN connection using native code in
Android?
And if so does the VPN offer support for keep alives?
I believe it would be more of a permissions issue than of an exposed or not exposed issue. Most VPN connections would need you to modify and access the network filtering calls of your kernel. Since your app should really be operating in it's own sandbox this is something I would doubt is exposed by default (to apps at least) since you would essentially be modifying the way the entire OS routes network traffic. For the same reason that in order to modify iptables in the OS, it needs to be rooted so that your app can actually alter such things. At that point I would assume the connection would be made similar to any other vpn connection in any other linux os (via an ipsec daemon or some proxy dameon that you create), but the calling entity would need the actual access level necessary to complete the call to the kernel.
Rooting of the device is needed for creating a VPN connection. We need access to /data/misc/keystore and /data/misc/vpn/profiles in our programm.
I am developing Enterprise applications that need to connect to
servers behind the firewall. Can my app start VPN connection
programmatically?
On 2.0+ platforms, VPN is supported by the platform. Assuming user
has already setup VPN parameters, can my app start the VPN
connection? Suppose user has not setup any VPN parameters, can my app
supply those parameters? and start VPN connection?
We're facing this problem at our shop. For now our best shot is trying to use Android internal API to connect to the VPN the same way that the system preferences app does.
First, you need to set up an environment that allows you to access internal API: http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/
Then we can implement something like this http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.4.4_r1/com/android/settings/vpn2/VpnSettings.java#258
I don't know if we will have any permission issues with this, but IMHO this is the best option we have right now
EDIT: this need root privileges in order to avoid java.lang.SecurityException: Unauthorized Caller errors.
Suppose user has not setup any VPN parameters, can my app supply those parameters? and start VPN connection?
yes, I think it's possible with VpnService class as in this example
Assuming user has already setup VPN parameters, can my app start the VPN connection?
I'm looking for it also. I'm not sure, but I think maybe it can be done with android.net.vpn. See this
AnyConnect by Cisco has private API: http://www.cisco.com/c/en/us/td/docs/security/vpn_client/anyconnect/anyconnect30/administration/guide/anyconnectadmin30/acmobiledevices.html#71308
Yes you can start a VPN connection.what version of android are you using? this link should be useful . give details for better understanding.