bgroenks
bgroenks

Reputation: 1889

Android: NAT Traversal?

It appears to me that newer Android devices run behind a NAT, where the local address is an internal carrier or LAN address and the public address is the router or carrier assigned external address.

Nevertheless, newer phones don't return the same address using the NetworkInterface as when accessing an IP detection service.

Therefore, connecting via direct P2P SocketChannels inherently fails.

Are there any common workarounds to this problem designed for the Android platform? Can anyone clarify what is causing this NAT-like security issue?

Any links to Java NAT traversal tutorials or examples (NOT essays or theses) would also be appreciated as being helpful (as I'm not quite sure how to implement it in Java).

I will of course also accept any other solutions anyone has to offer!

Upvotes: 10

Views: 10683

Answers (4)

user1028880
user1028880

Reputation:

I do that in my own project and have found this issue is not that complicated.

Here's a very simple UDP echo server in node.js

var dgram = require('dgram');

var socket =
    dgram.createSocket('udp4');

socket
    .on('listening', function()
    {
        var address = socket.address();
        console.log('socket listening ' +
            address.address + ':' + address.port);
    })
    .on('error', function(err)
    {
        console.log('socket error:\n' + err.stack);
        socket.close();
    })
    .on('message', function(message, rinfo)
    {
        console.log('message: ' + message + ' from ' +
            rinfo.address + ':' + rinfo.port);

        var msg = new Buffer(rinfo.address + ':' + rinfo.port);
        socket
            .send(msg, 0, msg.length,
                rinfo.port, rinfo.address,
                function(err, bytes)
                {
                    //socket.close();
                });

    })
    .bind(15000);

An android client simply send a msg to this node server

System.out.println("UDP hole punching=======================");

class IOth extends Thread {
    @Override
    public void run() {

        String sendMsg = "UDP hole punching";
        byte[] buf = sendMsg.getBytes();
        DatagramPacket packet;

        System.out.println(HPremoteHost); // node server IP
        System.out.println(HPremotePort); // 15000
        try {
            packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(HPremoteHost), HPremotePort);
            ds.send(packet);
        } catch (Exception e) {
            System.out.println("error================");
            System.out.println(e);
        }
    }
}
IOth io00 = new IOth();
io00.start();

Android Client UDP listener to obtain general msg and your own Global ip&port via UDPholepunching

class IOLoop extends Thread {
    @Override
    public void run() {
        try {
            String msg = "Native.UDPserver.open";
            SocketAddress sockAddress;
            String address;
            byte[] buf = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            while (true) {
                try {
                    ds.receive(packet);
                    sockAddress = packet.getSocketAddress();
                    address = sockAddress.toString();

                    msg = new String(buf, 0, packet.getLength());

                    System.out.println(msg + "  received !!! by " + address);

                    // this case is UDP HolePunching reaction
                    if (address.equals(HPaddress1)) {
                        System.out.println(msg + "hole punched");

                        // So you can obtain own Global ip& port here.
                        // exchange this information
                        // `remoteHost` `remotePort` to another client
                        // with some method (signaling server)
                    }
                } catch (IOException e) {
                }
            }
        } catch (Exception e) {
        }
    }
}
IOLoop io00 = new IOLoop();
io00.start();

Android Client UDP sender using other client's IP remoteHost remotePort

class IOth extends Thread {
    @Override
    public void run() {
        String sendMsg = "This is a test message";
        byte[] buf = sendMsg.getBytes();
        DatagramPacket packet;

        try {
            packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(remoteHost), remotePort);
            ds.send(packet);
        } catch (Exception e) {
        }
    }
}
IOth io00 = new IOth();
io00.start();

Upvotes: 3

Moises Jimenez
Moises Jimenez

Reputation: 1962

I've managed to establish sockets just by forwarding the sockets you're using during the connection in your router. It worked for me.

UPDATE

Find out your IP address through cmd.exe if your using Windows (ipconfig) or through a terminal session if your on Linux (ifconfig). Then connect to it through the browser and there should be a security section. Go to port forwarding and open up the ports your using when establishing you're ServerSocket and Socket. Use TCP as the protocol. Please note that this only applies if you're trying to connect from outside your wlan.

Upvotes: 0

jose
jose

Reputation: 11

Look at http://sourceforge.net/projects/jnat-pmplib/ It is an implementation of NAT-PMP in java.

Upvotes: 1

Yusuf X
Yusuf X

Reputation: 14633

Almost every phone or PC you will ever touch won't have a static public IP address, and therefore will require NAT traversal. It's not because of the device; the carrier or ISP put routers between your device and the public internet. Depending on your application, usually there are NAT-traversal libraries you can use, such as ice4j or STUNT.

Upvotes: 6

Related Questions