What's the difference between a TELNET and TCP session?
I have a simple server:
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(5555);
Socket socket = ss.accept();
System.out.println("Waiting for a client...");
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(sout);
out.writeUTF("\u001B[2J");
out.writeUTF("Hello client\r\n");
while (true) {
int b = sin.read();
sout.write(b);
}
}
I'm connecting via telnet and typing like this:
So I assume that packet sending by telnet client has no specific headers and pass to low level protocol (TCP in my case) completely without changing. Is it correct?
From http://en.wikipedia.org/wiki/Telnet#Telnet_data:
All data octets except 0377 are transmitted over the TCP transport as is. Therefore, a Telnet client application may also be used to establish an interactive raw TCP session, and it is commonly believed that such session which does not use the IAC (0377 character, or 255 in decimal) is functionally identical.[citation needed] This is not the case, however, because there are other network virtual terminal (NVT) rules, such as the requirement for a bare carriage return character (CR, ASCII 13) to be followed by a NULL (ASCII 0) character, that distinguish the telnet protocol from raw TCP sessions.[clarification needed] On the other hand, many systems now possess true raw TCP clients, such as netcat or socat on UNIX and PuTTY on Windows, which also can be used to manually "talk" to other services without specialized client software. Nevertheless, Telnet is still sometimes used in debugging network services such as SMTP, IRC, HTTP, FTP or POP3 servers, to issue commands to a server and examine the responses, but of all these protocols only FTP really uses Telnet data format.
Another difference of Telnet from a raw TCP session is that Telnet is not 8-bit clean by default. 8-bit mode may be negotiated, but high-bit-set octets may be garbled until this mode was requested, and it obviously will not be requested in non-Telnet connection. The 8-bit mode (so named binary option) is intended to transmit binary data, not characters though. The standard suggests the interpretation of codes 0000–0176 as ASCII, but does not offer any meaning for high-bit-set data octets. There was an attempt to introduce a switchable character encoding support like HTTP has,[3] but nothing is known about its actual software support.
I would type some more but really Wikipedia covered it nicely :)
Telnet is a name of services. and TCP is protocol to connect computer together with reliable, ordered, error-checked delivery of a stream.
Related
When we send data (in this case) to a client/server, does this really matter to use the same port number?
My guess is no, because it doesn't matter which port you are using when sending data to. (The protocol gives it to you randomly internally - this is the idea?) The only thing has to be kept, the port has to be any availabe one on the receiver machine(above 1000, because those are reserverd by the system), and if that receiver decides to send something back, he or she will have enough information about sender: his IP address, port number ect. As far as i know, a received packed provides with all of that info.
Below is just an illustration of what i've said above.
public class Server {
public static void main(String[] args) {
GameServer server = new GameSever(9822);
server.start();
InetAddress address = null;
int port = 7877;
try {
address = InetAddress.getByName("192.168.0.2");
} catch (UnknownHostException e) {
e.printStackTrace();
}
server.send(new byte[] { 1, 2, 3 }, address, port);
}
}
When a server listens on a computer, it specifies a port it wants it's connections coming in from , so ports are important for setting up servers. This is useful as you can have multiple applications listening on different ports without the different applications accidentally talking to eachother. So you should decide on a port that isn't a standard( 80 is for HTTP for example) to exclusively use for you gameserver so the client knows which port to send the requests to.
If you want to handle multiple connections at once the best thing to do is threading.
When we send data (in this case) to a client/server, does this really
matter to use the same port number? My guess is no, because it doesn't
matter which port you are using when sending data to.
Firstly, use the terms client and server distinguishly(as generally client initiates by sending the message, to which the server responds).
Next, the port which you're using is logically of no significance, the reason being server uses request.getPort() to determine the port while seding the response; (request is a DatagramPacket sent by the client).
Though you can hardcode the port at server(if known beforehand), but, it is a bad idea. What in those applications where you've no idea about who sent the datagram packet?
Java documentation by Oracle also uses an example of client-server where client's port number is left for the constructor to pick. It mentions :
Mostly, the client uses a constructor that does not require a port number. This constructor just binds the DatagramSocket to any available local port.
It doesn't matter what port the client is bound to because the DatagramPackets contain the addressing information. The server gets the port number from the DatagramPackets and send its response to that port.
MORE INFO (taken from Java Network Programming) :
public DatagramSocket() throws SocketException
This constructor creates a socket that is bound to an anonymous port. For example:
DatagramSocket client = new DatagramSocket();
Pick this constructor for a client that initiates a conversation with a server. In this scenario, you don’t care what port the socket is bound to because the server will send its response to the port from which the datagram originated. Letting the system assign a port means that you don’t have to worry about finding an unused port. If, for some reason, you need to know the local port, you can find out with the getLocalPort() method.
NOTE : The same socket can receive the datagrams that a server sends back to it(underlying implementation).
Whereas, the below constructor creates a socket that listens for incoming datagrams on a particular port, specified by the port argument :
public DatagramSocket(int port) throws SocketException
Use this constructor to write a server that listens on a well-known port.
Short answer:
Your guess is correct.
Longer answer:
Client gets a random port number when sending data to a server and each packet has a header which contains the info about client's port, ip address ect. So server can easily retreive this information and send anything back.
Whereas the server needs to be bind to a specific port in order to clients be able to send data to that server because when you use UDP, you need to specify an IP address and a port.
I'm writing a ServerSocket in java. I want to send some special content to client connecting to me through telnet. I want to send other content if he/she connects through Browser and etc. Is there any way to find out that user is connecting to me with telnet?
My code :
public void handleConnection(Socket socket) throws IOException {
String author = "Ehsan Akbari";
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
if(checkoutClientType(socket)=="telnet")
out.println("You are connecting through telnet :\)");
else
out.println("You are not connecting through telnet :|");
}
What should be the definition of checkoutClientType(Socket s);?
You cannot tell what program is on the other side of a socket by examining the socket itself. There is no test or operation you can perform on the socket that will distinguish the client program.
The only hope is to examine the data being transmitted to see if it matches an expected pattern, but for that you have to have some data transmitted. It might be possible to tell if the remote is telnet if you were to send a Telnet Protocol command such as AYT (Are You There), but that would probably not sit well with a different client such as a browser.
If you were able to proxy the data between the client and a handling process or thread and examine it you might be able to eventually determine if it was Telnet, but probably not, and probably not immediately.
I have a application (acting as the server) written in c that is listening on a raw socket, with this socket descriptor: socket(AF_UNIX, SOCK_RAW, 0);. The 0 indicates IPPROTO_IP
I want to write a code in java (acting as the client) to send an ip packet to this raw socket that is listening. Now i read around that java needs a 3rd party library to manage raw sockets. People recommend junixsocket and juds so i'll use one of them i guess.
Junixsocket does something like this to define a raw socket:
File socketFile = new File("/path/to/your/socket");
AFUNIXSocket sock = AFUNIXSocket.newInstance();
sock.connect(new AFUNIXSocketAddress(socketFile));
So the question is:
Is it possible to make these 2 applications communicate with eachother through this raw socket? In java you need to establish the socketfilename and path whereas in c thats not compulsory. My c code does not specify a socketfilename or path so i dont know how to make them communicate on the same socket. How do i make sure they're both sending/receiving on the same raw socket? All this communication is happening only in local!
Thank you
You are using the unix domain sockets (AF_UNIX). They are effectively designed for processes running on the same kernel, and use filesystem pathnames for addressing (see man 4 unix for details). So you have to share a pathname between both processes.
Edit as requested:
To set up the unix domain socket in C app, you need an address of type sockaddr_un, and fill up its sun_path member with a path to your socket:
sockaddr_un sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sun_family = AF_UNIX;
strncpy(sockaddr.sun_path, "/path/to/your/socket", UNIX_MAX_PATH);
and either bind() or connect() your socket to this sockaddr.
However, it has nothing to do with SOCK_RAW. Correct me if I am wrong, but you want a raw socket over the Internet, that is socket(AF_INET, SOCK_RAW, 0).
I was wondering if there was a way to open a pipe between a java serversocket and a bash tcp pipe. If so how would you do this. I know how to setup the java server side but how do you open the socket connection via bash or even a windows cmd prompt. Basically i want to pipe standard input into the tcp connection and receive standard output from it.
Any examples apprechiated!
-TJ
A ServerSocket can't do anything expect accept incoming connections, and create new Sockets which you use as endpoints (you don't use the ServerSocket for any send or recv operations). This is fine, but be aware of what side of the connection needs to accept connections. I'd assume it would be Bash since this seems to 'own' the pipe, so you'd use a Socket instead and connect that.
Use any of the SSH tools (there are a bunch opensources, e.g., ganymade) Ref:
http://java-source.net/open-source/network-clients/ganymed-ssh-2-for-java
I have not used this particular one, but other ssh clients to do what you want.
PS: You really do not need a ServerSocket for this, but use of threads is helpful.
Netcat is usually used to open TCP connections from a Unix shell. Bash (or any other shell I'm aware of) doesn't support it directly. There seem to exist a Windows port of Netcat too, but I haven't used it.
But it's a much better idea to just use SSH, as no special setup is required on the Java side in this case - you'll just get your standard I/O streams redirected to the SSH client automatically, with free encryption and optional compression (ssh -C) as bonuses. The disadvantage is that it would require installing an SSH server on the Java side and an SSH client on the connecting side.
Here is an example - the classes Connection, Session, etc. are defined in the imports.
At the time we were using the trilead SSH, and I dont think it is available publicly any more, but you can find a lot of other libraries on the web, e.g., http://linuxmafia.com/ssh/java.html
The point is, we did not have to open a serversocket to (1) establish an SSH session, (2) do a password authentication, (3) run some command at the user's login shell, and (4) grab its stdout. I believe most SSH libraries will give you this functionality. Hope this help, - M.S.
public void runCommand (String uName, String pWord, String cmd) throws Exception {
Connection conn = new Connection ("localhost");
conn.connect();
boolean authenticated = conn.authenticateWithPassword (uName, pWord);
if (!authenticated)
throw new Exception ("Authentication failure");
Session sess = connection.openSession();
sess.execCommand (cmd);
BufferedReader br = new BufferedReader (new InputStreamReader (
new StreamGobbler (sess.getStdout())));
for (String s = br.readLine() ; s != null ; s = br.readLine()) {
// do stuff with s
}
br.close();
sess.close();
conn.close();
}
Has anyone out there done the work of sitting on top of a packet capture interface (like jpcap) with an implementation of UDPSocket (for UDP datagrams) and InputStream (for TCP streams)?
I suppose it wouldn't be too hard to do given the callback API in jpcap, but has anyone out there already done it? Are there any issues with doing this (do I have to figure out how to reassemble a TCP stream myself, for example?)
I have not done this particular thing, but I do do a lot of work with parsing captured packets in C/C++. I don't know if there exist Java libraries for any of this.
Essentially, you need to work your way up the protocol stack, starting with IP. The pcap data starts with the link-level header, but I don't think there's much in it that you're concerned about, other than ignoring non-IP packets.
The trickiest thing with IP is reassembling fragmented datagrams. This is done using the More Fragments bit in the Flags field and the Fragment Offset field, combined with the Identification field to distinguish fragments from different datagrams Then you use the Protocol field to identify TCP and UDP packets, and the Header Length field to find the start of the corresponding header.
The next step, for both TCP and UDP, is demultiplexing, separating out the various connections in the captured packet stream. Both protocols identify connections (well, UDP doesn't have connections per se, but I don't have a better word handy) by the 4-tuple of the source and destination IP address and the source and destination port, so a connection would be a sequence of packets that matches on all 4 of these values.
Once that's done, for UDP, you're just about finished, unless you want to check the checksum. The Length field in the UDP header tells you how long the packet is; subtract 8 bytes for the header and there's your data.
TCP is somewhat more complicated, as you do indeed have to reassemble the stream, This is done using the sequence number in the header, combined with the length. The sum of these two tells you the next sequence number in the stream. Remember that you're keeping track of the traffic in two directions.
(This is a lot easier than writing an actual TCP implementation, as then you have to implement the Nagle algorithm and other minutiae.)
There's a lot of information on the net about the header formats; google "IP header" for starters. A network analyzer like Wireshark is indispensable for this work, as it will show you how your captured data is supposed to look. Indeed, as Wireshark is open source, you can probably find out a lot by looking at how it does things
Tcp reassembly can be done with JNetPcap. Here is a complete example:
final String SOME_PORT = 8888;
StringBuilder errbuf = new StringBuilder();
Pcap pcap = Pcap.openOffline("/dir/someFile.pcap", errbuf); //Can be replace with .openLive(...)
if (pcap == null) {
System.err.printf("Error: "+errbuf.toString());
return;
}
//Handler that receive Tcp Event one by one
AnalyzerListener<TcpStreamEvent> handler = new AnalyzerListener<TcpStreamEvent>() {
#Override
public void processAnalyzerEvent(TcpStreamEvent evt) {
JPacket packet = evt.getPacket();
Tcp tcp = new Tcp();
if (packet.hasHeader(tcp)) {
//Limiting the analysis to a specific protocol
if (tcp.destination() == SOME_PORT || tcp.source() == SOME_PORT) {
String data = new String(tcp.getPayload());
System.out.println("Capture data:{"+data+"}");
}
}
}
};
TcpAnalyzer tcpAnalyzer = JRegistry.getAnalyzer(TcpAnalyzer.class);
tcpAnalyzer.addTcpStreamListener(handler, null);
//Starting the capture
pcap.loop(Pcap.LOOP_INFINATE, JRegistry.getAnalyzer(JController.class), null);