While searching the internet for existing solutions I bounced over the so called "Nat Holepunch".
See the article on wikipedia .This actually made that much sense to me, I started developing my own proof of concept.
Details
At first I will describe the Server, as it is the basic component. This is the so called "Relay Server".
RelayServer.java
package de.boehme.app.natholepunch;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.HashSet;
import java.util.Set;
import de.boehme.app.natholepunch.dto.NATDevice;
public class RelayServer {
private Set<NATDevice> inquiredComputers = new HashSet<NATDevice>();
public static void main(String[] args) {
RelayServer rs = new RelayServer();
try {
rs.startServer();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void startServer() throws IOException, InterruptedException {
DatagramSocket serverSocket = new DatagramSocket(12345);
byte[] receiveData = new byte[50];
while (true) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
System.out.println("Listening...");
serverSocket.receive(receivePacket);
String data = new String(receivePacket.getData());
//NAT Device 1
InetAddress incomingIPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
NATDevice startComp = new NATDevice();
startComp.setPortOfNAT(port);
startComp.setPublicIpOfNAT(incomingIPAddress);
//NAT Device 2
String accordingIP = data.substring(0, data.indexOf(0));
// String accordingPort = data.substring(data.indexOf(':')+1, data.indexOf(0));
NATDevice destinationComp = new NATDevice();
// destinationComp.setPortOfNAT(Integer.valueOf(accordingPort));
destinationComp.setPublicIpOfNAT(InetAddress.getByName(accordingIP));
System.out.println("Checking: "+startComp.getPublicIpOfNAT()+":"+startComp.getPortOfNAT()+" TO: "+destinationComp.getPublicIpOfNAT());
//check here if a matching entry is already present
NATDevice matchComp = checkMatchingNATDevice(destinationComp);
if(matchComp != null){
System.out.println("Already present.. now sending packets to both of them...");
//send to the socket from previously saved first NAT Device infos from the second NAT Device
sendPacket(serverSocket, matchComp, startComp);
Thread.sleep(1000);
sendPacket(serverSocket, startComp, matchComp);
inquiredComputers.remove(startComp);
inquiredComputers.remove(matchComp);
} else{
System.out.println("Adding "+startComp.getPublicIpOfNAT()+":"+startComp.getPortOfNAT()+" AND "+destinationComp.getPublicIpOfNAT()+" for later matching");
inquiredComputers.add(startComp);
}
}
// serverSocket.close();
}
private synchronized NATDevice checkMatchingNATDevice(NATDevice comp){
for(NATDevice c : inquiredComputers){
if(c.getPublicIpOfNAT().equals(comp.getPublicIpOfNAT())){
return c;
}
}
return null;
}
private synchronized void sendPacket(DatagramSocket socket, NATDevice natDeviceHome, NATDevice natDeviceRemote) throws IOException{
byte[] sendData = new byte[50];
InetAddress homeIPAddress = natDeviceHome.getPublicIpOfNAT();
int homePort = natDeviceHome.getPortOfNAT();
//now the remote destination
InetAddress destIPAddress = natDeviceRemote.getPublicIpOfNAT();
int destPort = natDeviceRemote.getPortOfNAT();
String data = destIPAddress.getHostAddress()+":"+destPort+"-"+homePort;
sendData = data.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, homeIPAddress, homePort);
socket.send(sendPacket);
}
}
Explanation of the code:
The server should be run on a machine that can accept connections on port 12345. This is because the server listens on this specific port number.
Note: As this is only for development purposes the port number was hardcoded, i.e. when in production systems you would create it dynamically.
Going onwards to the most important method: startServer();
In the while loop we can see that on every connection attempt we differentiate between NAT Device 1 and NAT Device 2. How does this work? From the received packet we get a port number and an IP Adress. Both are needed to create a new object "NatDevice". In the data part of the packet we can extract the information we need to get the according second NAT Device.
The combination of NAT Device 1 to NAT Device 2 will be then added to an internal HashSet. That means when now NAT Device 2 connects to the server and the according NAT Device 1 is already present both NAT Devices get informed with the connection credentials of their connection peer.
How does the Client Side look like?
ClientBehindNAT.java
package de.boehme.app.natholepunch;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
public class ClientBehindNAT {
private String relayServerIP;
private String destinationIP;
private InetAddress clientIP;
private int socketTimeout;
public static void main(String[] args) {
ClientBehindNAT c = new ClientBehindNAT();
boolean result = c.parseInput(args);
if(result == true){
try {
c.createHole(true);
} catch (SocketTimeoutException e) {
System.out.println("Timeout occured... Try again?");
} catch (IOException e) {
e.printStackTrace();
}
} else{
System.err.println("Usage: <Relay Server IP> (e.g. 192.168.40.1) <Destination IP> (e.g. 192.168.40.128) <Timeout> (in milliseconds)");
}
}
/**
* Main method used for outer access
* @param standAlone
* @return the free NAT port of the Firewall
* @throws IOException
*/
public synchronized int createConnectionToPeer(String relayServerIP, String destinationIP, int socketTimeout) throws SocketTimeoutException, IOException{
this.relayServerIP = relayServerIP;
this.destinationIP = destinationIP;
this.socketTimeout = socketTimeout;
return createHole(false);
}
private boolean parseInput(String[] args){
if(args.length < 3){
return false;
} else if(args[0].equals("") || args[1].equals("") || args[2].equals("")){
return false;
}else{
relayServerIP = args[0];
destinationIP = args[1];
socketTimeout = Integer.valueOf(args[2]);
return true;
}
}
private int createHole(boolean standAlone) throws SocketTimeoutException, IOException{
// InetAddress serverIPAddress = InetAddress.getByName("192.168.40.1");
clientIP = InetAddress.getLocalHost();
byte[] addrInByte = createInternetAddressFromString(relayServerIP);//{(byte) 192, (byte) 168, 40, 1};
InetAddress serverIPAddress = InetAddress.getByAddress(addrInByte);
int port = 12345;
String data = destinationIP;
System.out.println("Try to send: "+data+" TO: "+serverIPAddress+" ON PORT: "+port);
//first send UDP packet to the relay server
DatagramSocket clientSocket = new DatagramSocket();
clientSocket.setSoTimeout(socketTimeout);
sendPacket(clientSocket, serverIPAddress, port, data);
//now wait for the answer of the server
String peer = receivePacket(clientSocket);
clientSocket.close();
//need to make sure all had the chance to receive packets with infos
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return initPeerConnection(peer, standAlone);
}
private byte[] createInternetAddressFromString(String address){
byte[] inetAddressBytes = new byte[4];
int index = address.indexOf('.');
int i=0;
while((index = address.indexOf('.')) != -1){
int part = Integer.valueOf(address.substring(0, index));
inetAddressBytes[i] = (byte) part;
address = address.substring(index+1);
i++;
}
inetAddressBytes[i] = (byte) Integer.valueOf(address).intValue();
return inetAddressBytes;
}
private synchronized void sendPacket(DatagramSocket socket, InetAddress destIPAddress, int port, String data) throws IOException{
byte[] sendData = new byte[data.length()];
sendData = data.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, destIPAddress, port);
socket.send(sendPacket);
}
private synchronized String receivePacket(DatagramSocket socket) throws SocketTimeoutException, IOException{
byte[] receiveData = new byte[50];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
socket.receive(receivePacket);
String answerFromServer = new String(receivePacket.getData());
answerFromServer = answerFromServer.substring(0, answerFromServer.indexOf(0));
System.out.println(clientIP+" GOT FROM SERVER:" + answerFromServer);
return answerFromServer;
}
private synchronized int initPeerConnection(String peer, boolean standAlone) throws IOException{
String accordingIP = peer.substring(0, peer.indexOf(':'));
String accordingPort = peer.substring(peer.indexOf(':')+1, peer.indexOf('-'));
InetAddress destIPAddress = InetAddress.getByName(accordingIP);
int remotePort = Integer.valueOf(accordingPort);
int natPort = Integer.valueOf(peer.substring(peer.indexOf('-')+1));
//this only applies in stand-alone mode
if(standAlone){
Thread receiver = new Thread(new PeerReceiveThread(natPort));
receiver.start();
Thread sender = new Thread(new PeerSendThread(destIPAddress, remotePort));
sender.start();
}
return natPort;
}
private class PeerReceiveThread implements Runnable{
int natPort;
public PeerReceiveThread(int port){
this.natPort = port;
}
public void run() {
try {
DatagramSocket serverSocket = new DatagramSocket(natPort);
byte[] receiveData = new byte[50];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
System.out.println(clientIP+" listening on port: "+natPort);
while(true){
serverSocket.receive(receivePacket);
String data = new String(receivePacket.getData());
System.out.println(clientIP+" FROM "+destinationIP+" WITH "+data);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private class PeerSendThread implements Runnable{
InetAddress destIPAddress;
int port;
public PeerSendThread(InetAddress destIPAddress, int port) throws UnknownHostException{
this.destIPAddress = destIPAddress;
this.port = port;
}
public void run() {
try {
DatagramSocket clientSocket = new DatagramSocket();
while(true){
sendPacket(clientSocket, destIPAddress, port, "Hello from "+clientIP);
Thread.sleep(2000);
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
The basic principle works like this: (code taken from own videochat application)
ClientBehindNAT c = new ClientBehindNAT();
dataPort = c.createConnectionToPeer(relayServerIP, destAddress, 15000);
controlPort = c.createConnectionToPeer(relayServerIP, destAddress, 15000);
At first we create a new ClientBehindNAT object and then calling createConnectionToPeer() method. This leads to a connection attempt to the listening RelayServer. As we have defined a timeout of 15 seconds the Client won't wait for too long, in case the other peer didn't get connected to the server or any other unforeseen problem occured.
The most important part is the createHole() method. Inside of this method we define the set up to the relay server by sending an initial packet to it. After that we wait until a packet comes back or the timeout occurs.
When everything went well, we extract the valid port number from the data part of the received message and return it back to the method caller.
Download Source Code:
complete Maven Project
natholepunch.zip
i'm not sure this is a udp hole punching implementation. I think the relay server should only give ip:port of client1 to client2 (and vice versa) so they can communicate without any relay server, by "punching" the nat with udp packets ip1:port1 <-> ip2:port2. On Client1, by punching paquets to ip2:port2 of client2, he can receive response from client2 because the client1's nat thinks that these packets are response from client1 paquets (same behaviour for client2's nat). So i think your code is only a kind of udp proxy : paquets are always sent to the relay server.
ReplyDeleteCorrect me if i'm wrong. Sorry for my english, i'm french.
Great Article Artificial Intelligence Projects
DeleteProject Center in Chennai
JavaScript Training in Chennai
JavaScript Training in Chennai
Hi, Download link is down ? any chances of getting natholepunch.zip ?
ReplyDeleteLink is down! Please email file on vitrag007@gmail.com
ReplyDeletePlease email me source on phanthai.uit@gmail.com thanks!
ReplyDeleteLink is down... :( i need natholepunch.zip file
ReplyDeletePlease email on 0verman2ya@gmail.com
Thanks all !!!
Interesting Article
ReplyDeleteOnline Java Training | Core Java Online Training
Interesting Article
Online Java Training | Java EE Online Training
Java Training Institutes in Chennai Java Training in Chennai
ReplyDeleteLink is down... :( i need natholepunch.zip file
ReplyDeletePlease email on msshin@iges.kr
Thanks all !!!
Link is down... :( i need natholepunch.zip file
ReplyDeletePlease email on msshin@iges.kr
Thanks all !!!
ReplyDeletelaw college
law college in Jaipur
Best law college in Jaipur
Law Course In Jaipur
Top College Of law In Jaipur
Vidyasthali Law College
Best Law College
Jaipur Law College
organic cold pressed oils
ReplyDeletenatural cold pressed oils
organic oil
organic oil in jaipur
organic cold pressed oil in jaipur
natural oil
natural oil shop in jaipur
pure herbal oil
ayurvedic oil store in jaipur
ayurvedic oil
Thanks for sharing this unique information with us. Your post is really awesome. Your blog is really helpful for me..
ReplyDeleteTop college in Jaipur|law college|law college in Jaipur|Best law college in Jaipur
Hey Your site is awesome and full of information. I have read you posts they are so informative. Keep Posting wonderful content.
ReplyDeleteAni international provide the security solutions for all kind of secruity system and other equipment.
Home security system in jaipur
Wireless Home Security System in jaipur
Realtime attendance machine in jaipur
CCTV Camera dealer in jaipur
Hikvision DVR in jaipur at Rajasthan
security system solutions in jaipur
website design in jaipur
website development company in jaipur
seo company in jaipur
Thanks for sharing this unique information with us. Your post is really awesome. Your blog is really helpful for me..
ReplyDeleteorganic oil
organic oil in jaipur
organic cold pressed oils
ayurvedic oil store in jaipur
Thanks for sharing this unique information with us. Your post is really awesome. Your blog is really helpful for me..
ReplyDeletehospital equipment
sarthak maditech
hospital equipment suppliers
hospital equipment manufacturers
medical equipment manufacturers in jaipur
operation theater lights
hospital suction machine
alcohol breath tester
hospital furniture manufacturer
ReplyDeleteI have read your blog its very attractive and impressive. Nice information. It helped me alot.
Government vacancy
Govt Jobs
Sarkari nokri
latest sarkari vacancy
Online Form
latest govt jobs
I have read your blog its very attractive and impressive. Nice information. It helped me alot.
ReplyDeletebest smartphone
best smartphone in india
best android phone
best mobiles phones 2020
best smartphone in india under 15000
I have read your blog its very attractive and impressive. Nice information. It helped me alot.
ReplyDeleteGovernment vacancy
govt jobs
latest govt jobs
Sarkari nokri
govt jobs Adda
govt recruitment
latest sarkari vacancy
It was really nice to read a blog post. I have been a huge fan of your blog posts for many years. Thanks for always being there Oxygen cylinder price in bangladesh
ReplyDeleteMedical Home Care BD
Oxygem cylinder bd
instagram takipçi satın al - instagram takipçi satın al - tiktok takipçi satın al - instagram takipçi satın al - instagram beğeni satın al - instagram takipçi satın al - instagram takipçi satın al - instagram takipçi satın al - instagram takipçi satın al - binance güvenilir mi - binance güvenilir mi - binance güvenilir mi - binance güvenilir mi - instagram beğeni satın al - instagram beğeni satın al - polen filtresi - google haritalara yer ekleme - btcturk güvenilir mi - binance hesap açma - kuşadası kiralık villa - tiktok izlenme satın al - instagram takipçi satın al - sms onay - paribu sahibi - binance sahibi - btcturk sahibi - paribu ne zaman kuruldu - binance ne zaman kuruldu - btcturk ne zaman kuruldu - youtube izlenme satın al - torrent oyun - google haritalara yer ekleme - altyapısız internet - bedava internet - no deposit bonus forex - erkek spor ayakkabı - webturkey.net - minecraft premium hesap - karfiltre.com - tiktok jeton hilesi - tiktok beğeni satın al - microsoft word indir - misli indir
ReplyDeleteyoutube abone satın al
ReplyDeletetrendyol indirim kodu
cami avizesi
cami avizeleri
avize cami
no deposit bonus forex 2021
takipçi satın al
takipçi satın al
takipçi satın al
takipcialdim.com/tiktok-takipci-satin-al/
instagram beğeni satın al
instagram beğeni satın al
btcturk
tiktok izlenme satın al
sms onay
youtube izlenme satın al
no deposit bonus forex 2021
tiktok jeton hilesi
tiktok beğeni satın al
binance
takipçi satın al
uc satın al
sms onay
sms onay
tiktok takipçi satın al
tiktok beğeni satın al
twitter takipçi satın al
trend topic satın al
youtube abone satın al
instagram beğeni satın al
tiktok beğeni satın al
twitter takipçi satın al
trend topic satın al
youtube abone satın al
takipcialdim.com/instagram-begeni-satin-al/
perde modelleri
instagram takipçi satın al
instagram takipçi satın al
takipçi satın al
instagram takipçi satın al
betboo
marsbahis
sultanbet
instagram takipçi satın al
ReplyDeleteucuz takipçi
takipçi satın al
https://takipcikenti.com
https://ucsatinal.org
instagram takipçi satın al
https://perdemodelleri.org
https://yazanadam.com
instagram takipçi satın al
balon perdeler
petek üstü perde
mutfak tül modelleri
kısa perde modelleri
fon perde modelleri
tül perde modelleri
https://atakanmedya.com
https://fatihmedya.com
https://smmpaketleri.com
https://takipcialdim.com
https://yazanadam.com
yasaklı sitelere giriş
aşk kitapları
yabancı şarkılar
sigorta sorgula
https://cozumlec.com
word indir ücretsiz
tiktok jeton hilesi
rastgele görüntülü sohbet
fitness moves
gym workouts
https://marsbahiscasino.org
http://4mcafee.com
http://paydayloansonlineare.com
instagram takipçi satın al
ReplyDeleteucuz takipçi
takipçi satın al
https://takipcikenti.com
https://ucsatinal.org
instagram takipçi satın al
https://perdemodelleri.org
https://yazanadam.com
instagram takipçi satın al
balon perdeler
petek üstü perde
mutfak tül modelleri
kısa perde modelleri
fon perde modelleri
tül perde modelleri
https://atakanmedya.com
https://fatihmedya.com
https://smmpaketleri.com
https://takipcialdim.com
https://yazanadam.com
yasaklı sitelere giriş
aşk kitapları
yabancı şarkılar
sigorta sorgula
https://cozumlec.com
word indir ücretsiz
tiktok jeton hilesi
rastgele görüntülü sohbet
erkek spor ayakkabı
fitness moves
gym workouts
https://marsbahiscasino.org
http://4mcafee.com
http://paydayloansonlineare.com
takipçi satın al
ReplyDeletetakipçi satın al
takipçi satın al
marsbahis
ReplyDeletebetboo
sultanbet
marsbahis
betboo
sultanbet
swrv coin hangi borsada
ReplyDeleterose coin hangi borsada
ray coin hangi borsada
cover coin hangi borsada
xec coin hangi borsada
tiktok jeton hilesi
tiktok jeton hilesi
tiktok jeton hilesi
tiktok jeton hilesi
thanks admin great article HDE Bilişim
ReplyDeleteAlışveriş
Compo Expert
Multitek
Seokoloji
Vezir Sosyal Medya
Adak
Maltepe Adak
tiktok jeton hilesi
ReplyDeletetiktok jeton hilesi
referans kimliği nedir
gate güvenilir mi
tiktok jeton hilesi
paribu
btcturk
bitcoin nasıl alınır
yurtdışı kargo
seo fiyatları
ReplyDeletesaç ekimi
dedektör
instagram takipçi satın al
ankara evden eve nakliyat
fantezi iç giyim
sosyal medya yönetimi
mobil ödeme bozdurma
kripto para nasıl alınır
instagram beğeni satın al
ReplyDeleteyurtdışı kargo
seo fiyatları
saç ekimi
dedektör
fantazi iç giyim
sosyal medya yönetimi
farmasi üyelik
mobil ödeme bozdurma
bitcoin nasıl alınır
ReplyDeletetiktok jeton hilesi
youtube abone satın al
gate io güvenilir mi
binance referans kimliği nedir
tiktok takipçi satın al
bitcoin nasıl alınır
mobil ödeme bozdurma
mobil ödeme bozdurma
smm panel
ReplyDeletesmm panel
İsilanlariblog.com
İnstagram takipçi satın al
hirdavatci burada
Www.beyazesyateknikservisi.com.tr
servis
tiktok jeton hilesi
pendik toshiba klima servisi
ReplyDeletependik beko klima servisi
ataşehir beko klima servisi
maltepe lg klima servisi
beykoz lg klima servisi
üsküdar lg klima servisi
tuzla lg klima servisi
tuzla daikin klima servisi
ümraniye toshiba klima servisi
Good content. You write beautiful things.
ReplyDeletesportsbet
sportsbet
hacklink
vbet
mrbahis
korsan taksi
taksi
vbet
hacklink
Success Write content success. Thanks.
ReplyDeletedeneme bonusu
betmatik
canlı slot siteleri
canlı poker siteleri
betpark
betturkey
kralbet