Java implementation of NAT Traversal / HolePunching TPC - java

I've been browsing and searching for implementation of a Peer-to-Peer TCP Connection with both clients behind routers, but everything I got was "get more confused"!
My case is "a little bit simplest", since I already KNOW the local and public IP addresses from both sides.
So, at this point I just DON'T NEED TO USE THIRD SERVER to discover those informations.
Client A: (LocalIP="192.168.0.1", PublicIP="a.a.a.a").
This client will be Listening to connection on port "pppp"
serverSocket = new ServerSocket("pppp");
serverSocket.setSoTimeout(timeOut);
socket = ClientA.serverSocket.accept();*
Client B: (LocalIP="10.10.0.1", PublicIP="b.b.b.b")
This client will will try to connect to "Client A" on port "pppp"
SocketAddress sockaddr = new InetSocketAddress("a.a.a.a", "pppp");
socket.connect(sockaddr, timeOut);
Of couse it will not work, so given those informations, how to proceed?

Related

Difference between Socket & InetSocketAddress?

I searched a lot but I was not able to find a direct difference between the two. When do we use each one when it comes to creating a client socket?
An InetSocketAddress does not manage a Socket in any way.
I think you mean Socket vs DatagramSocket.
Socket is for connections communicating via TCP (reliable).
DatagramSocket is for connections communicating via UDP (unreliable).
Or, if you're referring to SocketAddress vs InetSocketAddress:
SocketAddress is simply the abstract implementation of a Socket Address with no protocol.
InetSocketAddress is an implmentation of SocketAddress, for IP.
It is all in the name... A typical network socket is a connection between two ports on two machines.
The ServerSocket is the one that waits for clients to connect to it.... it 'binds' to a port, and it 'Listens' for connections, and when they happen, it 'accepts' the connection. The result of the accepted connection is a Java Socket. The client that connected (if it is also Java), also has a Java Socket. You now have two sockets connected to each other.
The Socket is described above.
Now, the address is the details about how to find/identify the remote side of the Socket connection.
A SocketAddress is the abstract class for something that can tell Java where to connect to when contacting a server, and it allows the Sockets to identify remote servers/clients once the connection is made.
An InetSocketAddress is a special SocketAddress designed to represent the standard TCP Protocol address, so it thus has methods to set/query the host name, IP address, and Socket of the remote side of the connection (or, in fact the local side too).
So, the (Inet)Socket address is used to establish Socket connections...
Summary:
ServerSocket is a listener that waits for socket connections to be established.
Socket is the communication channel between two systems (one the server, the other the client).
SocketAddress is an abstract class that identifies an address
InetSocketAddress is a class that is specific for the TCP protocol consisting of IP Addresses/host-names, and port numbers. This is used to establish internet/TCPIP sockets.
Reference taken from
https://softwareengineering.stackexchange.com/questions/231150/whats-the-difference-between-socketaddress-and-serversocket-in-java
From the Javadoc for Socket
This class implements client sockets (also called just "sockets"). A socket is an endpoint for communication between two machines.
and for InetSocketAddress
This class implements an IP Socket Address (IP address + port number)
The address is like the location of your house, the Socket is the road which leads to that house.
A SocketAddress is the abstract class for something that can tell Java where to connect to when contacting a server, and it allows the Sockets to identify remote servers/clients once the connection is made.
An InetSocketAddress is a special SocketAddress designed to represent the standard TCP Protocol address, so it thus has methods to set/query the host name, IP address, and Socket of the remote side of the connection (or, in fact the local side too).

How to change source-ip(tcp) in Java

Is it possible to change TCP header in Java?
If it's possible, is there any [Change Header] method?
Answering the more narrow question from the title of your question ("How to change source ip in Java"), you can bind your socket to a local IP address and/or port before you connect it to a destination.
The IP address you bind to has to be an IP address that your machine has (otherwise, how could packets arrive back at your machine?). You can also take any unused, non-reserved port number to connect from.
Socket socket = new Socket();
socket.bind(new InetSocketAddress(9999));
// or: socket.bind(new InetSocketAddress(InetAddress.getByAddress(...), 9999));
socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 80));
More generally, the answer is no, you cannot just randomly change the TCP header. But there are plenty settings that you can do from Java that will affect what goes into the TCP header.
I'm wondering whether you'r thinking about to cheat the server by providing a random source ip. As far as I know, there's no way to do this in java.
And even if you have changed your ip address, i think you can not successfully "hand-shake" with the server, which means you can not establish a TCP connection with the server side.

Using same address and port for accepting and connecting in Java

(This might have been asked a thousand times, but I do not get it straight.)
Suppose I have the following snippet:
InetAddress localAddress = InetAddress.getByName("192.168.1.10");
int localPort = 65000;
InetAddress targetAddress = InetAddress.getByName("192.168.1.20");
int targetPort = 65000;
// Create a new serversocket
ServerSocket ss = new ServerSocket(localPort, 50, localAddress);
// Wait for an incoming connection...
Socket acceptedSocket = ss.accept();
// Do something with the accepted socket. Possibly in a new thread.
Set up new connection...
Socket socket = new Socket(targetAddress, targetPort, localAddress, localPort);
// Write something to the socket.
Now can I use the same address and port for both accepting an incoming connection and connecting to an address? If it can, then how? If not, then why not? According to this post, ports can be shared, so it shouldn't be a problem.
How does it work?
You can only establish a connection by having the connecting socket use the same address and port. (Ignoring the use of multi-homed servers)
A single connection is a unique combination of both the source address+port and destination address+port, so you can have the same destination if you have a different source.
In other words, can you write server program that that contains client connecting to itself? The answer is yes, surely. All integration tests do this running in-process server and connecting to it.

Get domain name of incoming connection

I don't find any information on this topic on the internet and asked here. For example I have server with IP 1.1.1.1 and 2.2.2.2 and two domain names pointing to it one.example.com and example2.net, and socke listening on port 1234 for incoming connections.
For example:
C/C++:
listenfd=socket(AF_INET, SOCK_STREAM, 0);
bind(...);
listen(...);
while(...) accept(...);
or Java:
ServerSocket socket = new ServerSocket(1234);
while(...) {
Socket connectionSocket = welcomeSocket.accept();
...
}
When client accepted on my socket I need to know what domain name/IP is used by the client to connect. It may be one.example.com or example2.net and/or IP 1.1.1.1 or 2.2.2.2 (if connected using IP only).
Apache somehow determined ip/domain of incoming reques, and I need to do such thing in pure socket code. C++ (main) or Java (or any other) accepted, I need to know mechaniics of this.
The IP is stored inside the IP packet header and you can read it from there. In order to get the host, you'll probably have to ask a DNS server by sending a request (or use a function which does it for you). You can find examples for both of the problems, even on this site

Connect two computer over http without public IP

I'll like to computers/clients to connect directly to each other in the case where one or both of them haven't got a public IP. I guess this could be done with a server as a middle man. The connection established in the end must be direct traffic between the clients. How is this possible, and what is the technic called?
I'll really like to see some code fx in Java.
Thanks
If port forwarding is not an option, there is a mostly-reliable technique you can use with UDP traffic called NAT traversal. It requires a middle-man server to act as a rendezvous point, but after the initial set-up all traffic will be endpoint-to-endpoint.
This will not work in all cases; it depends on how the various NAT layers map external endpoints to internal entpoints.
TCP NAT traversal is very difficult to implement and has an extremely low chance of even working.
(I have successfully used UDP NAT traversal to establish an OpenVPN connection between two computers at different universities, both behind several NAT layers!)
You will propably have to use hole punching (TCP or UDP) if both parties are behind NAT. Something like this:
socket = new DatagramSocket(port);
volatile boolean connectionEstablished = false;
volatile boolean reveivedSomething = false;
Sender-Thread:
while (!connectionEstablished) {
byte[] buf = new byte[256];
buf[0]=reveivedSomething?1:0;
DatagramPacket packet = new DatagramPacket(buf, buf.length,
otherpcpublicaddr, otherpcsport);
socket.send(packet);
Thread.sleep(500);
}
Receiver-Thread:
while (true) {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
reveivedSomething=true;
if (buf[0]==1) {
connectionEstablished=true;
break;
}
Thread.sleep(500);
}
(you would have to do this on both PCs and to exchange IPs and ports using some reachable server as long as they aren't static)
I don't know of a Java fix, but you could use a dynamic dns service to re-route the traffic into the non-public ip. I think they use a client that keeps track of the public client IP that is assigned by their ISP, and reports it to the service, which then updates their host table. There may also be some configuration needed on each system's routers, in order to forward the public request into the private ip.
There would be several techniques used to perform this, port forwarding, NAT, Dynamic DNS, etc

Categories