Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NAT-PMP support #7

Open
offbynull opened this issue Jan 9, 2014 · 2 comments
Open

NAT-PMP support #7

offbynull opened this issue Jan 9, 2014 · 2 comments

Comments

@offbynull
Copy link

Would it be possible to add NAT-PMP support to this library? The protocol seems stupid easy -- much less convoluted than UPnP IGD. http://miniupnp.free.fr/nat-pmp.html has a good overview of the protocol. Here's an example that I jut wrote that grabs your exposed IP address and opens a port for 60 seconds (tested on my home router):

    public static void main(String[] args) throws Throwable {
        DatagramSocket datagramSocket = new DatagramSocket(10000 + new Random().nextInt(55535));

        DatagramPacket publicAddressRequest = new DatagramPacket(new byte[] { 0, 0 }, 2, InetAddress.getByName("192.168.1.1"), 5351);
        datagramSocket.send(publicAddressRequest);

        ByteBuffer publicAddressResponseBuffer = ByteBuffer.allocate(12);
        DatagramPacket publicAddressResponse = new DatagramPacket(publicAddressResponseBuffer.array(), publicAddressResponseBuffer.capacity());
        datagramSocket.receive(publicAddressResponse);

        System.out.println(Integer.toHexString(publicAddressResponseBuffer.getInt(8))); // my ip

        DatagramPacket newPortMappingRequest = new DatagramPacket(new byte[] { 
            0, // version
            1, // udp (for tcp choose 2)
            0, 0, // reserved
            0x10, 0x00, // private port
            0x10, 0x00, // public port
            0, 0, 0, 60 // time to live for mapping
        }, 12, InetAddress.getByName("192.168.1.1"), 5351);
        datagramSocket.send(newPortMappingRequest);

        ByteBuffer newPortMappingBuffer = ByteBuffer.allocate(12);
        DatagramPacket newPortMappingResponse = new DatagramPacket(newPortMappingBuffer.array(), newPortMappingBuffer.capacity());
        datagramSocket.receive(newPortMappingResponse);

        System.out.println(Integer.toHexString(publicAddressResponseBuffer.getShort(2))); // result code
    }

The only issue with this is that there doesn't seem to be a standard way of getting the default gateway address in Java (192.168.1.1 in the example).

@abahgat
Copy link
Member

abahgat commented Jan 20, 2014

I would be happy to implement this, but my present router does not seem to support it. I am, however, getting a new device this week that might support this.
However, I did some cursory research during the weekend and I stumbled upon the same problem: there does not seem to be any way to get the gateway address without relying on OS-dependent commands. I am not really fond of this approach, as it might not work for some platforms (e.g. Android?)

If we could find a way to get this to work in 100% Java and platform independent code, I would definitely love to have this in weupnp.

@offbynull
Copy link
Author

Sorry, the delay in response lead me to believe this project had been abandoned. I ended up writing an implementation under my own p2p project: https://code.google.com/p/peernetic/source/browse/#git%2Frouter-natpmp%02Fsrc%2Fmain%2Fjava%2Fcom%2Foffbynull%2Fpeernetic%2Frouter%2Fnatpmp.

Regarding the gateway address, I don't think there's much that can be done to make this platform independent. I used two approaches to try to get around this problem:

  1. Common gateway addresses: I hardcoded a list of common IP router addresses from http://www.techspot.com/guides/287-default-router-ip-addresses/
  2. Run "netstat -rn" and scrap the output for IPv4 addresses: This should work on Linux/OSX/Windows, but not other playforms like Android :(

The third solution I thought about was trying to do an exhaustive scan of internal addresses. This may be do-able for class C range, but class A and B ranges are too large.

My router (ASUS RT-N56U) is NAT-PMP enabled. I think internally it uses miniupnpd. I was able to get everything working except listening for external address change broadcasts. I don't know if this is an issue with my router or with the code I wrote.

Also, the other day I came across some information that says that there's a newer version of NAT-PMP called PCP (http://tools.ietf.org/html/rfc6887). My understanding is that PCP needs a gateway address as well and has a similar request/response structure, but supports IPv6 and large scale NATs as well (and possibly chained NATs?).

If you're still interested in NAT-PMP/PCP support (even thought it won't be a 100% Java solution), we should pool our efforts together under a single banner and make sure that we don't end up duplicating effort/work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants