I am trying to write a basic C client/server program using sockets in Unix. I am logging on my school's Unix server from my home computer. I am logging on twice, once to simulate the server and the other to simulate the client. Do I use AF_INET or AF_UNIX? Whose IP address should I use, the one from my home computer or my school? If I use my school's IP address, how do I find out what it is? How do I find out what port number I should use? Does the port number for my client and server have to be the same?
Usually you'll want to use AF_INET — then you'll be able to communicate between more than one computer later.
Use 127.0.0.1; that means "this computer".
Make up a port number and use it for both. Usually you'll want to pick something between 1024 and 65536, exclusive.
Since the programs are running on the schools computer you should use that IP address.
You can use the command /usr/sbin/ifconfig -a to find it (it's the inet address). However, if both logins are at the same physical computer (for example at my school that isn't always the case) you can just use 127.0.0.1.
You can use any port number you want, but choose a high (like four digits) since the lower ones are default for some services.
The port numbers for the client and server do not have to be the same, but it might be easier for you to remember if they are.
See here for a lot of examples. There is some stuff you have to understand:
TCP, UDP and the difference between them
What is a socket, types of sockets (stream, datagram, sequential packets)
Socket API's - BSD, POSIX, WinSock (if you're planning to program for Windows)
Related
I've been reading lately about DNS cache-poisoning attacks. Essentially they are possible simply because an attacker can guess the DNS message transaction ID, since it is only a 16-bit integer. Even if the integer is random, it's still possible for a flurry of DNS packets to coincidentally match 1 of 2^16 packets in a short time window.
So a second security measure is port randomization. If the UDP source port is random, an attacker would have to guess both the source port and the transaction ID in a short time window, which is usually not feasible. But I read that older versions of DNS software such as BIND versions before 9 did NOT perform port randomization, and are therefore vulnerable.
This brings me to the question: don't most UNIX OS's like Linux and BSD automatically assign random ports when a SOCK_DGRAM is used without a prior call to bind? I thought that was the whole idea with ephemeral ports. Why does an application (like BIND) have to go out of it's way to perform port randomization?
My understanding is that, essentially, an OS like Linux will have a RANGE of ephemeral ports available for use with each process. A process can call bind() to bind a UDP socket to a specific port. But if a UDP socket is used (i.e. send is called) without first calling bind, the OS will lazily assign a random ephemeral port to the socket. So, why were older versions of BIND not performing port randomization automatically?
This brings me to the question: don't most UNIX OS's like Linux and BSD automatically assign random ports when a SOCK_DGRAM is used without a prior call to bind? I thought that was the whole idea with ephemeral ports.
The main idea of ephemeral ports is not to be random in a secure way, but just to pick some unused port fast. Different OS use different strategies, some do it a bit random, some use a stronger random generator and some assign the ports even in a sequential way.
This means not on all OS ephemeral ports are unpredictable enough for use with DNS.
For more details I would recommend to study RFC 6506 "Port Randomization Recommendations" and the overview about port selection strategies at https://www.cymru.com/jtk/misc/ephemeralports.html.
I'm writing a program in C in which the server listens on a well known port, waits for client to connect, and then creates a random port for the client to use and send this port number back to the client. My main difficulty is how to create a "random" port. Should I just be using srand and create a random 4 digit port is the usable range? Or is there a better way to do this? I know that if I use port 0 a port will be chosen for me but the problem here is the fact that I don't think i can "get/see" the actual value of the port so that I can send this port number back to the client.
Thanks...
Binding port 0 is the solution. It gives you an arbitrary port, not a random port, but this is what many applications do (e.g. FTP etc).
After binding, you can use getsockname to figure out which port you got.
What you do is bind() with port set to 0. The system will assign one. Then use getsockname() to discover what port the system assigned. Send that back to the client. That way there is no race condition and you follow any system rules for port assignment.
A random 4-digit port checked to make sure it's not in use is OK for that purpose..
Technically speaking, it sounds like you're trying to implement this for added security (some kind of primitive port knocking routine)? It might be worth mentioning that this approach is generally not considered too secure. It also imposes some artificial constraints on how many clients you can serve at a time and actually adds unnecessary load on the server. Why not just listen on the single well-known port for all clients?
I'm guessing TCP considering your description of listening and automatic port assignment by the OS. In this case, you don't need to worry about it. Once you accept the TCP connection, the OS on both sides takes care of all that you're trying to do and you're left with a working connection, ready for use. Unless you have a particular reason for doing any of this yourself, it's already done for you.
Currently, I'm working on TCP client/server implementation in C. In that, I found that I can give any random number as a port number for my PC. Is it correct procedure? Or is there any standard port number for my PC?
I don't know the standard, but I say it's not. At least, I don't like to do it like that.
You can check occupied ports by parsing the outputs of programs like netstat and avoid using those. You can also use the method that attempts connecting on one port, and upon failure, tries another port. Unless you're really really unlucky, you should get a valid port on second try.
You should use ports within the ranges of 49152–65535. Ports below 49152 are reserved/registered.
Basically, you can use any port (given sufficient access rights). But server and client have to agree on the port, and it should not be already used by another application.
Hence, many ports are already reserved for special applications. 80 is for HTTP, 22 is for SSH and so on. The file /etc/services gives more detailed information.
Port numbers 0-1023 are called Well Known Ports, numbers 1024-49151 are called Registered Ports (not all of them are, but you get the idea).
If your question is whether you can give any port number to have your server listening to,
then you are thinking wrong, TCP/IP port numbers below 1024 are special in that normal users are not allowed to run servers on them, you can use non-privileged ports(ports > 1024). just make sure that any other application is not already using that port (above 1024) using netstat
I have a course project where I'm suppose to present some networking stuff. There are great chances that I have to do it on one computer. So my question is, how do I show a communication between tcp/ip or tcp/udp? I'm not a networking expert, I understand the concept of sending data which is red. And I think I need two IP addresses.
You don't need two IP addresses. Just start the server on the machine, and have the client connect to address 127.0.0.1 and the appropriate port. (This address always refers to the same machine the program is running on.)
You can run a virtual machine on your computer and work on network between them.
How, in C, can I detect whether a program is connecting to itself.
For example, I've set up a listener on port 1234, then I set up another socket to connect to an arbitrary address on port 1234. I want to detect whether I'm connecting to my own program. Is there any way?
Thanks,
Dave
Linux provides tools that I think can solve this problem. If the connection is to the same machine, you can run
fuser -n tcp <port-number>
and get back a list of processes listening to that port. You can then look in /proc and found out if there is a process with a pid not your own which is running the same binary you are. A bit of chewing gum and baling wire will help keep the whole contraption together.
I don't think you can easily ask questions about a process on another machine.
One of the parameters to the accept() function is a pointer to a struct sockaddr.
When you call accept() on the server side it will fill in the address of the remote machine connecting to your server socket.
If that address matches the address of any of the interfaces on that machine then that indicates that the client is on the same machine as the server.
You could send a sequence of magic packets upon connection, which is calculated in a deterministic way. The trick is how to do this in a way that sender and receiver will always calculate the same packet contents if they are from the same instance of the program. A little more information on what your program is would be helpful here, but most likely you can do some sort of hash on a bunch of program state and come up with something fairly unique to that instance of the program.
I assume you mean not just the same program, but the same instance of it running on the same machine.
Do you care about the case where you're connecting back to yourself via the network (perhaps you have two network cards, or a port-forwarding router, or some unusual routing out on the internet somewhere)?
If not, you could check whether the arbitrary address resolves to loopback (127.0.0.1), or any of the other IP addresses you know are you. I'm not a networking expert, so I may have missed some possibilities.
If you do care about that "indirect loopback" case, do some handshaking including a randomly-generated number which the two endpoints share via memory. I don't know whether there are security concerns in your situation: if so bear in mind that this is almost certainly subject to MITM unless you also secure the connection.