Beispiel-Code für UDP Hole Punching

Hier mal ein Beispiel-Code für UDP HolePunching.
Hinweis : dieser Code ist nicht von mir, auch ich habe ihn nur so irgendwo im Netz gefunden.

Zu den Testbedingungen :

Client : privater Kabel-Anschluss, 128MBit/s down ; 6MBit/s up, fest IP, AVM FritzBox 6360 als Modem/Router, aktive NAT-Firewall (keine Portfreigaben), Kaspersky InternetSecurity 2014 als PersonalFirewall auf einem Win7 Ultimate x64 SP1, Oracle Java 8u20 x64
Server : KVM (Proxmox-Host, aktive Hardware-Virtualisierung), OpenSuSE 13.1 - 3.11.10-21-default, SuSEfirewall2 - externe Zone (keine Portfreigaben), OpenJDK 7u51

NAT.java

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;



public class NAT {

	public static void main(String[] args) throws Exception {
		
		if (args.length < 3) {
			System.out.println("USAGE: NAT [localport] [remoteIP] [remoteport]");
			return;
		}
		
		int localPort = Integer.parseInt(args[0]);
		String ip = args[1];
		int remotePort = Integer.parseInt(args[2]);
		
		System.out.println("Testing UDPTunneler");
		UDPTunneler tunnel = null;
		try {
			tunnel = new UDPTunneler(localPort,ip,remotePort);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("Initialized, creating tunnel.");
		
		try {
			tunnel.createTunnel();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("Yes, tunnel successfully created.");
		
	}

}```
UDPSender.java
```import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;


public class UDPSender extends Thread {

	String str,ip;
	int port;
	long interval;
	boolean run;
	DatagramSocket socket;
	
	public DatagramSocket getSocket() {
		return socket;
	}
	
	public void setStr(String str) {
		this.str = str;
	}
	
	public void send(String s) {
		byte[] data = s.getBytes();
		InetSocketAddress address = new InetSocketAddress(ip,port);
		
		DatagramPacket packet = null;
		try {
			packet = new DatagramPacket(data,data.length,address);
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		try {
			socket.send(packet);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public UDPSender(DatagramSocket sock,String ip, int port,String s, long i) {
		super();
		str = s;
		interval = i;
		run = true;
		this.socket = sock; 
		this.ip = ip;
		this.port = port;
		this.start();
	}
	
	public void terminate() {
		run = false;
	}
	
	public void run() {
		
		while(run) {
			
			this.send(str);
			
			try {
				Thread.sleep(interval);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}
	
}```
UDPTunneler.java
```import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.InetSocketAddress;
import java.net.InetAddress;


public class UDPTunneler {
	
	int lport,rport;
	String ip;
	DatagramSocket socket;
	
	public UDPTunneler(int localPort, String hostIP, int remotePort) throws Exception {
		lport = localPort;
		rport = remotePort;
		ip = hostIP;
		
		socket = new DatagramSocket(localPort);
	}
	
	public void createTunnel() throws IOException {
		UDPSender sender = new UDPSender(socket,ip,rport,"CONN",1000);
		
		while(true) {
			
			DatagramPacket p = new DatagramPacket(new byte[10], 10);
			socket.receive(p);
			
			//analyse
			String data = new String(p.getData());
			if (data.indexOf("CONN") != -1) {
				sender.send("CONN");
				sender.terminate();
				break;
			}
			
		}
	}

}```
Sicher, das kann man deutlich eleganter und aufgeräumter machen, aber wie gesagt : auch ich hab den Code nur so im Netz gefunden.

Wie an den obigen Angaben zu erkennen ist sind beide System selbst nach außen hin dicht und weisen auch bei direkten "Port-Scans" den Status "blocked" auf. Dank UDP-HP jedoch kommt trotz der aktiven Firewalls eine Verbindung zustande so das auf beiden Seite folgender Output kommt :

Testing UDPTunneler
Initialized, creating tunnel.
Yes, tunnel successfully created.


Weiterhin habe ich diesen Code schon erfolgreich zu anderen DSL-Anschlüssen mit dynamischer IP getestet.

Es soll also eher ein proof-of-concept sein als wirklich verwendbarer Code. Auch soll es eine Hilfestellung für die sein die sich damit befassen und Probleme haben so das man eine Art Referenz-Test hat falls der eigene Code nicht so funktionieren sollte wie man will.


An TCP HolePunching hab ich mich jetzt noch nicht gewagt da das natürlich auch ganz andere Anforderungen stellt und nicht weis ob ich das mit mener Kombination überhaupt erfolgreich testen kann, aber ich werds sicher mal irgendwann ausprobieren.

Schaut überraschend übersichtlich aus. Dachte da wäre mehr Code nötig :slight_smile:

Aber eigentlich gehört das mehr in’s Projekte-Unterforum.

Naja, wo es nun am besten passt kann ja ein Mod entscheiden. Ich habs hier gepostet weils halt der Themenbereich ist. Auch soll es mehr ein funktionierendes Beispiel anstatt eine Projektgrundlage sein.

Auch ist es eher Zufall das ich es überhaupt gepostet habe, aber nähere Hintergründe würden zu off-top führen.

Du siehst, mit so konkreten Angaben kommt man nicht sehr weit. Beschreibe was du machen willst, was du bereits versucht hast und wieso der Code den du gefunden hast bei dir nicht funktioniert. Irgendwie zählt nicht.:scheiterhaufen: