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.
Related
I have been testing the SCTP support on Java + lksctp.
I wrote a simple client in order to see just the inital setup of a SCTP association which is basically the "INIT" and "INIT ACK".
I have tested 2 ways for a Client to send the "INIT" to a SERVER which is basically:
create the SctpChannel object with "open(SocketAddress)"
try {
InetSocketAddress socketAddress = new InetSocketAddress("192.168.52.197", 2905);
SctpChannel sctpChannel = SctpChannel.open(socketAddress,1,1);
sctpChannel.bind(new InetSocketAddress("192.168.1.251",2906));
sctpChannel.connect(socketAddress, 1 ,1);
so in this way, I can see in Wireshark that I have the "IPv4 Address parameter" for all my network interfaces (3 as you can see bellow), but the Source Port is getting a aleatory port number instead the 2906 as I would like to have and it's in the bind.
So... once the bind of local IP/Port is happening after the "open"... so I have changed the code to:
create the SctpChannel object which just "open()"
binding the local client IP and Port
"connect" to the remote Server IP and Port
try {
InetSocketAddress socketAddress = new InetSocketAddress("192.168.52.197", 2905);
SctpChannel sctpChannel = SctpChannel.open();
sctpChannel.bind(new InetSocketAddress("192.168.1.251",2906));
sctpChannel.connect(socketAddress, 1 ,1);
In this way, I can see in wireshark that Source/Destination ports are expected (2906/2905), but the INIT does not have the "IPv4 Address parameter".
So does anyone know why the 2nd code I'm missing the "IPv4 address parameter" in the INIT ? Do I miss something?
Any help would be really welcome.
Thanks.
IP addresses within INIT/INIT_ACK chunks are optional parameters. In case your endpoints are signglehomed IP address might not be included in the INIT/INIT_ACK chunk. The remote end still can retrieve information about peer address from the IP header.
Fundamentally the reason of this behaviour is what parameters you pass to open(). Open() without any parameters and open() with remote address specified works in a different way.
If you call SctpChannel.open(socketAddress,1,1) with socket address for the remote end it effectively open channel and connects to remote end (see open documentation. Your bind() and connect() calls in this case are pretty useless. So since there were no bind() call prior to establishing the connection you are sort of using "default" endpoint with random port (56044) and IP addresses of all available interfaces.
In second case, when you don't specify socketAddress for open() it just open the channel but does not connect to remote end at this stage. So your bind() call successfully specify endpoint details (port and IP address) and when you call connect() it is actually using the endpoint you just created (192.168.1.251:2906) to setup connection with remote end.
I have programming a little Authentification System and I use this code to get the IP of the user:
DatagramSocket socket = new DatagramSocket(port);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
InetAddress address = packet.getAddress();
String ip = address.toString().replace("/", "");
My question is: Can we trust the value given with the string ip? Can somebody put a fake IP in a header of the packet?
It is very confusing, does a UDP header contain the IP of the sender of the UDP packet, if so can we change this header to modify with another IP?
In an established TCP connection, you can assume that the remote IP address is valid because otherwise you could not send anything back to the host (and the TCP handshake would not succeed -- see SYN flood).
However, you have no guarantee that the remote IP address actually belongs to your user, so it's a really bad way to perform authentication.
One of the commenters gave the example of a proxy. It doesn't have to be TOR: if you use the common practice of an NGINX or Apache server in front of your application, then you'll always get the IP address of that server (ie, your own server).
Also, we live in a world where most users are behind a NAT. Which means that you may have dozens or hundreds of distinct users that all appear to come from the same IP address.
And the IP address will potentially change. This is particularly common with connections made from cellphones
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).
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
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Here's the problem, it's very simple (to understand..):
I have 2 computers at home, they both have the same public IP address (e.g. 1.2.3.4).
I have 1 computer at a coffee place (different network) so it has a different public IP address.
I want to send a message (e.g. "hi") from the computer at the coffee place to ONE of computers I have at home.
I'm using Java, think of the following very simple program for the sender (I took off exception handling for simplicity):
In main I do:
sendPacket("hi");
and I have
void sendPacket(String message){
DatagramSocket myServerSocket = new DatagramSocket(9000); // server socket
byte[] sendData = new byte[message.length()]; // build msg
sendData = message.getBytes();
InetSocketAddress destSocketAddr = new InetSocketAddress("1.2.3.4", 9000); // destination socket addr
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, destSocketAddr); // make packet
myServerSocket.send(sendPacket); // send packet
}
If I have my listener (receiver) running on both computers at home (both with the same public IP address 1.2.3.4) how can I specify which one I intend to send this message to?
If both of your home computers have the same public IP address, that means those computers are using NAT or Network Address Translation (strictly speaking, it's Port Address Translation or NAT Overload, but commonly referred to as just NAT).
What this means is that in order to initiate a connection from the outside to any of your machines inside NAT, a Port Forwarding must be set in your router (typically your modem), so that you map a specific port of your public home IP address to a specific private IP address inside your home.
Let's say you have computers A and B in your home like this:
Router / Modem
192.168.0.1
||
++=========++========++
|| ||
Computer A Computer B
192.168.0.2 192.168.0.3
Now, let's assume you need Computer A listening on TCP port 9000 (ports can mainly be TCP or UDP), you could forward public port 9000 directly to Computer A's 9000 port:
Forward TCP/UDP on public port 9000 to private port 9000 on 192.168.0.2
To send a message to computer A, just send it to 1.2.3.4:9000. But what if the other PC only listens on port 9000 too? You cannot also assign public port 9000 because it is taken by Computer A. You could do this:
Forward TCP/UDP on public port 9001 to private port 9000 on 192.168.0.3
This way, computer B still receives messages on port 9000, but they would need to be sent across the Internet to 1.2.3.4:9001. Your router's NAT automatically translates the port as the data packets enter (and leave!) your home network.
In the end, the sender would need to adjust the destination port in order to 'talk' to different machines behind NAT.
Hope this makes sense.
Typically, these NAT firewalls will port-forward traffic back to the originating computer for you.
So, if you had one machine sending traffic to your coffeeshop machine on port 5000 and the other one sending traffic to the coffeeshop machine on port 5001, the router would keep track of which port is intended for which client. Thus, when you send packets back from port 5000 it'll go to the first machine, and when you send packets back from port 5001, it'll go to the second machine.
The unfortunate part is that your machine at the coffeeshop is probably also behind a NAT firewall, and your home machines may not be able to directly address it, either.
If you can host a server on a good network, then both peers can contact the server, and relay all traffic through it. That's not a bad option but it does not scale well. (For three machines, it's no big deal. For three million machines, it matters a lot.)
You can investigate other options to try to traverse the NAT firewall such as UPnP, but those mechanisms usually require some way for clients to negotiate sessions before they'll work.