Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a raw packet to a NetworkInterface in Android doesn't work?

I'm trying to send packets via a VPN out of the VPN onto the proper hardware without any real VPN server used, so I can log the packets being sent through.

I'm able to get an InetAddress for the wlan0 interface I want the packet to actually go to, but I'm not too sure if that's the right place at all (it shows my current IP address).

I then use a DatagramChannel (called socket and the IntetAddress is uplink) on it:

socket.connect(new InetSocketAddress(uplink, 0));

And write packets to it:

socket.write(packet);

But nothing sticks, I just get

java.net.SocketException: sendto failed: EINVAL (Invalid argument)
like image 494
Joe Simpson Avatar asked Aug 28 '12 14:08

Joe Simpson


2 Answers

I'm trying to do something similar in creating a firewall/filtering application for Android. I'm in the middle of this, so take what I say with the appropriate sized grain of salt. :-)

The trouble with your/my situation is that you're taking packets off the virtual network interface given to you by VpnService, but then you're taking those packets and writing them out with a socket. A socket is intended to handle the transfer of application payload between client and server, not packets.

The socket will take any data you hand it, and wrap that data within a packet of its own creation (TCP if using Socket, UDP if using DatagramSocket as you are). In your case, the data you are handing the socket is itself a packet, and thus you end up with a packet within a packet (likely a TCP packet inside a UDP packet).

When the wrapped packet arrives at the server for your socket, the network interface and ServerSocket on that end will unwrap the payload and find that it is another packet. Probably not going to work because whatever is reading from the server-side socket (e.g. web server) is expecting application payload (e.g. HTTP headers/etc.).

Now, when you have a real VPN tunnel, the server-side of that tunnel is probably pulling your 'wrapped packet' payload out of the UDP packet it receives and is then handing that packet directly to a network interface that can interpret the packet itself.

Without this real VPN tunnel, your VpnService impl essentially has to become a virtual network interface itself, handling the TCP/UDP/etc. protocol between the virtual network interface and your code. Basically, packets read from your VPN interface have to be treated as an application data stream (packets collated and reassembled) before writing to your outgoing socket. Then, you have to somehow acknowledge the packets you just consumed from the interface. Then, you have to take incoming data from your Socket (which is a payload data stream), and break it up into packets that you can then send back to the output stream of your VPN interface. Finally, you need to handle acknowledgement traffic your virtual VPN interface will send in response to the packets you send it. This is not trivial to do.

I really hope I'm wrong about all this, and someone has a simple 'virtual network interface' written in Java that could be used to take the place of the real VPN tunnel. I haven't been able to find it.

like image 198
Mitch Upton Avatar answered Nov 25 '22 14:11

Mitch Upton


You can use NetworkInterface APIs to get wlan0 address programmatically.

I'm also trying to do similar thing.. I'm able to see packets at virtual interface.. But I'm not able to send packet via local interface..

I'm able to connect to wlan0 with DatagramChannel, but connection to outside server from wlan0 is stuck at SYN_SEND..

like image 30
Nilesh Shah Avatar answered Nov 25 '22 12:11

Nilesh Shah