Android VpnService Configuration - java

I am trying to use the VpnService from android to setup a simple tun device on the client side and on the receiving side I have a c++ server running.
I am having a lot of problems with the VpnService. This is what I need,
I need ALL packets outbound from the Android phone to be routed to the tun device, and in the program I route it through a Datagram channel to the server. When I send a string, it works fine, but when I send other data through this Datagram channel, i don't see any UDP packets in Wireshark :\
Also, I am new to Java and Datagram channels. Here Is my code
//To establish the tunnel
builder.setSession("MyVPNService")
.addAddress("192.168.56.0", 32)
.addDnsServer("8.8.8.4")
.addRoute("0.0.0.0", 1);
mInterface=builder.establish();
What exactly are the above configurations doing? Isn't a tun device supposed to have ONE IP(from my experience from doing it on linux), then what is ""192.168.56.0", 32". Also when i try to add a route "0.0.0.0", 0 the whole android phone hangs and restarts :\
while (true) {
int length;
// Read the outgoing packet from the input stream.
length=in.read(packet_bytes);
//int length = in.read(packet.array());
if (length > 0) {
// Write the outgoing packet to the tunnel.
//packet.limit(length);
//tunnel.send(packe,server);
tunnel.send(packet,server);
packet.put(packet_bytes,0,length);
tunnel.write(packet);
packet.clear();
}
Thread.sleep(200);
// Read the incoming packet from the tunnel.
length = tunnel.read(packet);
if (length > 0) {
out.write(packet.array(), 0, length);
packet.clear();
// If we were sending, switch to receiving.
}
Thread.sleep(200);
}
This is the part where I take it from interface and put it on the other.

First, let me start by explaining Builder configuration above.
builder.setSession("MyVPNService") // This one is optional.
.addAddress("192.168.56.0", 32) // This is used to assign interface address. First param is IP address, and second in prefix length. "Prefix" length is also commonly known as subnet mask.
.addDnsServer("8.8.8.4") // This configures the DNS network for VPN network. For ex - All DNS resolutions would go to 8.8.8.4:53. Note that the DNS request packets gets routed through the tun interface.
.addRoute("0.0.0.0", 1); // This controls the IP addresses which gets routed through tun interface.
Note - that tun interface can support multiple address families (IPv4/IPv6). As an example, you can assign multiple interface addresses (say a v4, a v6, or two v6 addresses, or whatever combo).
Similarly, you can add routes that you want your VPN to handle. Now, the main question is how do you decide which routes should my VPN handle?
Well there are bunch of options.
Route everything - Adding 0.0.0.0/0 (for IPv4), and ::/0 (for IPv6) would route traffic for all destinations through VPN (Note: 0.0.0.0/0 represents entire IPv4 range i.e. 0.0.0.0 to 255.255.255.255).
Route specific routes - You would have typically noticed that talking to IoT devices does not work when VPN is running. That is typically due to "route everything" config setup which breaks local networking (ex - chromecast). So, excluding link local traffic requires doing some math that involves subtracting link local subnets from above subnets (0.0.0.0/0, ::/0 (for v6 local subnets)). The math involved is not very straightforward which makes this option a lot more complex. As for what constitutes link local subnets, here is a list from wikipedia, and from IETF for IPv4 and IPv6 special addresses.
That said, here are some answers to your questions.
I need ALL packets outbound from the Android phone to be routed to the tun device
See "route everything" above.
Isn't a tun device supposed to have ONE IP?
An interface on linux can have multiple interface addresses assigned to it from different address families.
Then what is "192.168.56.0", 32".
As explained above, first part is the IP address, and second defines the subnet mask. Also see CIDR notation.
Also when I try to add a route "0.0.0.0", 0 the whole android phone hangs and restarts.
0.0.0.0/0 means entire IPv4 address space will get routed through the VPN. Typically, a VPN cannot handle link local traffic as I have mentioned above. So, you will have to exclude certain local subnets (see links above). As for phone hanging and restarting, I'm not sure if that has anything to do with the VPN unless VPN is not handling traffic correctly (which would lead networking related apps to break).

Related

Can a PINGREQ message be used by a gateway to update a network address in MQTTSN

Im using an MQTTSN Gateway Version 1.2 from;
https://github.com/simon622/mqtt-sn
I notice that a when a client connection goes to sleep and then subsequently wakes up, its IP address may well have changed on the network. When the next PINGREQ message is sent by a client, the gateway is unable to establish its identity from the network address and so the session simply times out.
Is there anyway of updating the network address in this scenario to tie it back to the original session without having the overhead of a new CONNECT?
I tried issuing a new PINGREQ, but the gateway was unable to link the new network address to an existing gateway session.
You're correct in stating that a client may well recycle their IP address during a network event (ie. a network stack power down, or roaming between cells on a cellular network). These events typically require a completely new CONNECT to be issued in order to re-authenticate with a gateway, since typically in SN UDP implementations, the network address is used as part of the identification mechanism. You can CONNECT(clean=false) to maintain session state.
Allowing a client to re-establish (or bind to an existing) session using a PINGREQ alone (with the presence of a clientId) would be very insecure and would present an easy attack vector for session hijacking.
Hope this helps clarify things.

Java server-client game

Ok, I am quite new to network programming and I am trying to solve this problem:
I have GUI based Java SE game for max 7 players and I want it to support multiplayer over the Internet.
Every instance of game would have its own client sending and receiving string.
And here comes the problem I cannot sufficiently solve. I need server and its only functionality is keeping client's sockets opened and on receiving some string just forward it to other clients. My first idea was to run server on the first player's machine and other players can connect to that server via its IP from outside. Now I discovered that getting public interface IP is not that easy as I thought so I searched and found the code written below to get some IP's that SHOULD be available from outside. When I try this at localhost, resulted IP is always some IPv6 + port and connecting from client using this credentials is successful and it works. When I start the server on another machine and copy these credentials for connecting from another computer it fails (it either doesn't connect or if it does and client sends message, server doesn't receive any).
So my next idea was to use some public IP on remote hosting server. So there would be some server running 24/7 (or if I programmatically from game tell him so) and I use its IP to unite all clients. I just don't know how to make this thing working and what technologies use.
I hope I explained my problem clearly and thanks for any ideas or even solutions :)
Get machine's public interface IP (where server is running) and prints that out code:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface iface = interfaces.nextElement();
if (iface.isLoopback() || !iface.isUp()) { //127.xxx loopback
continue;
}
Enumeration<InetAddress> addresses = iface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();
String tmp = addr.getHostAddress();
if (tmp.startsWith("192.168.") //local IP
|| tmp.startsWith("10.") //local IP
|| tmp.startsWith("172.16.") //local IP
|| tmp.startsWith("172.31.") //local IP
|| tmp.startsWith("169.254") //single network IP
|| tmp.equals("255.255.255.255")) { //broadcast address
continue;
}
//cut "%net9","%wlan" etc stuff off
IP = tmp.substring(0, Math.max(0, tmp.indexOf('%')));
port=server.getPort();
System.out.println(IP + " " + port);
}
}
if running on a "local network" then having a serversocket is fine, but we deal with NAT and the internet which means that 98% of machines are not directly internet visible. (i.e. opening a TCP port for listening on the machine will not result in the machines Internet IP address having that port be listened to. )
The initial option would be to have a server on public hosting which mediates communication between players and each players machine is responsible for maintaining 'game state' but then you run into the issue of synchronization. (e.g. one players machine thinks that they have hit and killed another player prior to that machine receiving a command to tell it that the opponent has moved. )
The current method of thinking for this paticular problem is to have the server maintain the 'game state' (e.g. player positions, health, weapon damage, etc. )
having players send 'commands' to the server (e.g. move, fire, jump. ) and then having the server report to all players the 'minor' game state changes. (so Time becomes an important factor and all messages between clients and server need to be timestamped. )
so your clients maintain what they believe 'game state' to be, recieving updates from the server to 'correct' errors.
In addition to this every once in a while the server should send a dump of the entire 'game state' to each player as a 'sync' message to ensure what they believe to be the game state 'is' the actual game state.
If your language of choice was "C" it would be trivial to take the md5 checksum of the entire game state structure and then transmit this to players periodically and only performing a sync message..
The links below should give you a good starting point.
A good start
And the enclosing page with a little bit more detail

why ip address differs when wireless is off?

public class Main {
public static void main(String[] args) throws IOException {
InetAddress myIp = null;
try {
myIp = InetAddress.getLocalHost();
} catch (UnknownHostException ex) {
System.out.println("Exception cought.");
System.exit(0);
}
System.out.println(myIp);
}
}
I have this simple question that why my ip address is different when my wireless is off?
it's still the same computer, so why does it change? (isn't this a unique number?)
The IP address of the computer depends on the network it's connected to (and indeed, the same machine may have more than one, if it has multiple adapers).
So if I connect my machine to one of my networks, it may have the address 192.168.10.7 whereas on another of my networks, it may be 192.168.17.12. It can vary between connections as well, although in practice they tend to be a bit sticky. (It depends on how the DHCP server is configured.)
Your adapter can be configured with a fixed address, but if you do that, it has to be an address the network it's connecting to has reserved for it. Otherwise it may not work at all ("No route to host") or may conflict with another machine using the network.
.An IP address is the address of a network adapter within a specific local network.
It will be different when connected to different networks.
When not connected to any network, it will either be a link-local address or an auto-configuration address.
You might want the MAC address, which is the hardware address of a single network adapter and is not very likely to change.
The provided code returns HOSTNAME/IP-Address(xx.xx.xx.xx).
Hostname is your computer name ex: MY-PC and then you get the IP corresponding to it.
When you are connected to a network, InetAddress.getLocalHost() asks the DHCP server in the network "what is the address of MY-PC (the name of your computer)", the DHCP replies -> 33.44.55.66
Try the following CMD commands when both connected and disconnected.
\>hostname
MY-PC
\>nslookup MY-PC
44.55.66.77
When you are not connected to a network there are two possibilities:
You do not get a hostname (default is localhost)
You do get a hostname, but there is no DHCP server on the network to return an IPaddress,
so you get loopback - 127.0.0.1
If you want to "call" your computer on the network locally, use the loopback http://www.pcmag.com/encyclopedia/term/57812/loopback-address
Hope this helps
No. You're confusing IP and MAC addresses. The MAC address is a serial number of hardware(but may be programatically changed on certain chipsets).
The IP address is either software-determined or determined by the network. It can differ between networks or even with time.
IP addresses are (usually) interface specific, not machine specific.
If your machine only has one interface the difference is moot, but it matters if (for example) you have both wired and wireless ethernet.
Also note that if you do have both and attempt to use them both at the same time on the same subnet that things will likely get very confused!

connect to a lacewing server chat

I'm trying to make a port of a chat program a friend of mine made with lacewing and multimedia fusion 2 for android device.
I've managed to create a socket connecting to the listening socket of the server successfully, but I cannot seem to be able to send data to login and enter the chat. The login for now just requires a name, but even if I send a String of data, the server doesn't seem to reply or accept that data to get me over the channel.
I know I could easily port this with other way like using the NDK of the multimedia fusion 2 exporter, but I just want to figure out how this works
PS: I'm using Java and libgdx for the development
You need to read the liblacewing relay protocol:
https://github.com/udp/lacewing/blob/0.2.x/relay/current_spec.txt
On initial connection, you have to send byte 0 to identify that you are not an HTTP client. After this, you can exchange normal protocol messages.
The first message you need to send is the connection request (which may be denied by the server with a deny message). This would be:
byte 0 (2.1.0 request)
(1.2 size)
byte 0 (2.1.0.0 connection request)
string "revision 3" (2.1.0.0 connection request -> version)
When the server responds with response 0 (2.2.0.0 Connect), you then have to set a name before you may join any channels. This is done with message 2.1.0.1 SetName, which is the same structure as above but instead of 2.1.0.0's byte 0, it is 2.1.0.1's byte 1, followed by the name as a string instead of the protocol version.
The server should then respond with 2.2.0.1 SetName, assuming it accepted your name change request. You should process this message in case the server gave you a different name than you requested. Finally, once you have a name, you can join a channel with 2.1.0.2 JoinChannel. The flags you specify here will be used if the channel doesn't exist yet (e.g. nobody is in the chat yet) - these should match the ones in the MMF2 project file. The name should also match.
After all that, you're still not done! You have to process more messages, etc. it's almost like writing the RelayClient class yourself. It's a tough task, but with the protocol specification in hand you should be able to work it all out.

How to send a UDP packet to a specific computer when all the computer on the network have the same public IP address? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Here's the problem, it's very simple (to understand..):
I have 2 computers at home, they both have the same public IP address (e.g. 1.2.3.4).
I have 1 computer at a coffee place (different network) so it has a different public IP address.
I want to send a message (e.g. "hi") from the computer at the coffee place to ONE of computers I have at home.
I'm using Java, think of the following very simple program for the sender (I took off exception handling for simplicity):
In main I do:
sendPacket("hi");
and I have
void sendPacket(String message){
DatagramSocket myServerSocket = new DatagramSocket(9000); // server socket
byte[] sendData = new byte[message.length()]; // build msg
sendData = message.getBytes();
InetSocketAddress destSocketAddr = new InetSocketAddress("1.2.3.4", 9000); // destination socket addr
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, destSocketAddr); // make packet
myServerSocket.send(sendPacket); // send packet
}
If I have my listener (receiver) running on both computers at home (both with the same public IP address 1.2.3.4) how can I specify which one I intend to send this message to?
If both of your home computers have the same public IP address, that means those computers are using NAT or Network Address Translation (strictly speaking, it's Port Address Translation or NAT Overload, but commonly referred to as just NAT).
What this means is that in order to initiate a connection from the outside to any of your machines inside NAT, a Port Forwarding must be set in your router (typically your modem), so that you map a specific port of your public home IP address to a specific private IP address inside your home.
Let's say you have computers A and B in your home like this:
Router / Modem
192.168.0.1
||
++=========++========++
|| ||
Computer A Computer B
192.168.0.2 192.168.0.3
Now, let's assume you need Computer A listening on TCP port 9000 (ports can mainly be TCP or UDP), you could forward public port 9000 directly to Computer A's 9000 port:
Forward TCP/UDP on public port 9000 to private port 9000 on 192.168.0.2
To send a message to computer A, just send it to 1.2.3.4:9000. But what if the other PC only listens on port 9000 too? You cannot also assign public port 9000 because it is taken by Computer A. You could do this:
Forward TCP/UDP on public port 9001 to private port 9000 on 192.168.0.3
This way, computer B still receives messages on port 9000, but they would need to be sent across the Internet to 1.2.3.4:9001. Your router's NAT automatically translates the port as the data packets enter (and leave!) your home network.
In the end, the sender would need to adjust the destination port in order to 'talk' to different machines behind NAT.
Hope this makes sense.
Typically, these NAT firewalls will port-forward traffic back to the originating computer for you.
So, if you had one machine sending traffic to your coffeeshop machine on port 5000 and the other one sending traffic to the coffeeshop machine on port 5001, the router would keep track of which port is intended for which client. Thus, when you send packets back from port 5000 it'll go to the first machine, and when you send packets back from port 5001, it'll go to the second machine.
The unfortunate part is that your machine at the coffeeshop is probably also behind a NAT firewall, and your home machines may not be able to directly address it, either.
If you can host a server on a good network, then both peers can contact the server, and relay all traffic through it. That's not a bad option but it does not scale well. (For three machines, it's no big deal. For three million machines, it matters a lot.)
You can investigate other options to try to traverse the NAT firewall such as UPnP, but those mechanisms usually require some way for clients to negotiate sessions before they'll work.

Categories