Bind a web server to port 80 without being root - c

I've written my own web server in C. How can I bind it to port 80 without being root so that the security is not being compromised (buffer overflows etc.)?
Should I simply forward any traffic from another "stable" server that runs on port 80?

Using a forward proxy is indeed the easiest and most recommended solution. It also has the advantage of filtering horribly invalid requests before they even reach your self-written server.
In case your application uses the user's ip address for something remember to retrieve it from whatever header your webserver uses (X-Client-IP etc.). However, only do so for requests that really come from your webserver, otherwise users can spoof their IP. You can do so by checking if the request came from your IP and only check the header in this case or simply make your application bind to localhost.
Another solution would be granting the program the CAP_NET_BIND_SERVICE capability. This requires root to use setcap cap_net_bind_service=ep /path/to/the/executable - since the flag is stored in a filesystem attribute, it will be lost when copying the file to another system or recompiling the application.
Of course you could also make your program setuid root and then switch to an unprivileged user right after calling bind(). However, depending on how your program works and what it does this might not be a good idea - for example, if it needs to close and reopen the listening socket for some reason it would require a full restart of the process.

An alternative to calling bind() as root, then dropping privileges, is to have a root process that creates the socket and binds it, and then passes the listening socket to the unprivileged process over a UNIX-domain socket connection using a SCM_RIGHTS message.

if you want to bind your server to port 80 you must do that as root and afterwards drop the privileges.
bind(sockfd, addr, addrlen);
/* process is running as root, drop privileges after bind*/
if (setgid(groupid) != 0)
errx(1, "setgid: Unable to drop group privileges: %s", strerror(errno));
if (setuid(userid) != 0)
errx(1, "setuid: Unable to drop user privileges: %S", strerror(errno));
How can I bind it to port 80 without being root so that the security is not being compromised (buffer overflows etc.)
not running as root does not make your system more secure it just adds another layer to exploit.
So instead of thinking about how not to run as root, please ensure that you do not use any known-insecure functions like strcpy(), sprintf(), etc. but instead use strncpy(), snprintf(), etc.

Well as you know all ports under 1024 in Unix require root privileges to open.
On a Unix system you do not want as few applications as possible running with root privileges.
It is and will always be a big safety risk.
An alternative is to use iptables to redirect the port 80 traffic to a more harmless port like 8080. Here is a description on how to set it up.
Iptables is not the easiest tool to setup, but once you have mastered it, it is very useful and powerful (and secure).

I worked on this problem for quite some time and came to the conclusion that systemd + iptables is the solution, and not Capabilities, as elaborated in great detail here.

Related

Linux Raw Socket Permissions Issue

I'm creating a raw ethernet socket in a C application, e.g.
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
and its returning -1 indicating an error
I'm pretty sure its a permissions issue - You can only open a raw socket if you have a UID of 0 (root) or have the CAP_NET_RAW capability
I don't think running the application as root is reasonable, therefore my question is how can I 'add' the CAP_NET_RAW capability permission to my user account?
From http://manpages.ubuntu.com/manpages/zesty/en/man7/packet.7.html
In order to create a packet socket, a process must have the CAP_NET_RAW
capability in the user namespace that governs its network namespace.
But how does one achieve that end?
You set the capabilities on the executable that needs that capability, not a user account. The syntax is
setcap cap_net_raw,cap_net_admin=eip ./your_exeutable
(Note, you need to run setcap as root, so use e.g. sudo setcap ... Also make sure there are no space characters in cap_net_raw,cap_net_admin=eip
Being able to read all network packets is considered a severe security risk, that is why this needs a privileged account.
You can make the application "suid root" to elevate your own rights when starting this application as a "normal" user. But that is a security risk as well and needs a bit of thorough thinking when designing the application (it should at least give up the higher privilege as soon as it doesn't need it any more - i.e. after having opened the raw socket).
You cannot add the CAP_NET_RAW permission to your account, because capabilities on Linux do not follow users. They follow executables.
To make this work, you need to add the CAP_NET_RAW capability to your compiled executable. See the setcap command in order to see how to do that.

What other non-default ports can i use for webserver?

I am using 80(http) and 443(https) default ports for my webserver.
What ther ports other than this can i use for my webserver.
I need this basically to start my webserver using non-default ports.
Any. Look at these for the ones to not use:
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
You can use whatever ports you want to use, provided no other server on your box is also trying to use it.
This is, of course, subject to any OS-specific issues like needing to run with elevated privileges for binding to ports below 1024.
The IANA (naming authority) and ICANN (assigned names and numbers) is responsible for assigning ports to specific applications but there's nothing requiring you to follow those "rules" at all.
If you use (for example) port 23 for your HTTP server, that will work. It's likely to confuse any telnet programs attempting to connect to that box but, as stated, the box is under your jurisdiction, not that of the IANA. Provided your browsers hook up to the specific port 23, they'll work just fine.
By way of example, many IBM mainframe systems will use port 23 for their 3270-protocol terminal programs and bump "real" telnet up to port 1023.
And, in any case, why should you not use a port because it's "allocated" to the Quake game server, or Dropbox, or Symantec bloatware? :-)

Recommended port for proxy server

I'm trying to create a proxy server, and am having trouble decide on a trivial thing -- the port number on which it will listen. Is there some kind of convention on which port a proxy server should run on? Or should it just be greater than 1024?
Normally, you just pick a port and make it changeable for the user (or yourself). Simply, if it is already used on the system you run your proxy on, use a different one.
Many free proxy servers even listen (e.g. this) to default ports, like 8080. As long as the port is not in use on your system, it does not matter, as the real port is negotiated after a connection attempt.
For your interest, a list of registered ports can be found on the IANA (Internet Assigned Numbers Authority), which manages stuff like that. That is only a hint. I normaly use a random port like 8888 or so, even if someone somewhere already uses that.

UNIX sockets: Is it possible to spoof getsockopt() SO_PEERCRED?

Is there a (compatible) way to spoof (as root) the unix socket (file system sockets) peer credentials which can be obtained by getsockopt(), option SO_PEERCRED?
Background:
I need to connect to a server application (which I cannot modify) which checks the UID of the process which connects to it via SO_PEERCRED. I'd like to spoof the information in order to be able to connect to the application as root, too.
UPDATE
To clarify the question:
I'm searching for a non-invasive way that the server sees a specific peer UID/GID.
Solutions are discouraged which need to alter the kernel (or take the use of kernel modules) or which changes the server process or its loading/linking process in any way (LD_PRELOAD, system call interceptions etc.).
Basically, the solution should work when running on any linux (or unix in general) server without any special requirements. The server process might already be running.
You're on the right lines. A root process has the privileges to spoof things like this, the problem is just that SO_PEERCRED provides no mechanism or API for a process to specify what identity should be to presented to the peer.
Two things you can do:
Temporarily drop root (setreuid(desired,-1)) when you make the connect call. A unix-domain connection is stamped with the credentials of the peer at the time the process called connect (and listen going the other way). SO_PEERCRED does not tell you the credentials of the peer at the current moment. Then you can resume root.
Better, use another API. The message-passing API lets a process pick what identify to present to a peer. Call sendmsg with a struct cmsg that contains the credentials you want to send. The kernel will ignore the credentials specified by an unprivileged user and always make sure the other side sees the actual identity, but a privileged process can pretend to be anyone else. This is a better match for your needs, because dropping and regaining root is a perilous activity and in this case unnecessary. Google for "SCM_CREDENTIALS" (or "man -K" for it on your system) to get code samples.
No. The reason is that the mechanism that provides the UID and GID of the peer is internal to the kernel, and you can't spoof the kernel! The kernel uses the PID of the peer to deduce the effective credentials of the peer. This happens when one side does a connect on the socket. See the call to copy_peercred() from unix_stream_connect() in net/unix/af_unix.c. There isn't any way that the peer can change the data it sends or the socket that will convince the kernel that the peer's PID isn't what it is. This is different from AF_INET sockets where the kernel has no internal knowledge of the peer's process and can only see the data in the IP packet headers that the peer sends.
The only thing that you can do to get this effect is to set the effective UID of the peer process to root or whatever UID/GID you want, and for that you need either root password or sudo privileges.

Bind failed: Address already in use

I am attempting to bind a socket to a port below:
if( bind(socket_desc,(struct sockaddr *) &server, sizeof(server)) < 0)
{
perror("bind failed. Error");
return 1;
}
puts("bind done");
But it gives:
$ ./serve
Socket created
bind failed. Error: Address already in use
Why does this error occur?
Everyone is correct. However, if you're also busy testing your code your own application might still "own" the socket if it starts and stops relatively quickly. Try SO_REUSEADDR as a socket option:
What exactly does SO_REUSEADDR do?
This socket option tells the kernel that even if this port is busy (in
the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,
but with another state, you will still get an address already in use
error. It is useful if your server has been shut down, and then
restarted right away while sockets are still active on its port. You
should be aware that if any unexpected data comes in, it may confuse
your server, but while this is possible, it is not likely.
It has been pointed out that "A socket is a 5 tuple (proto, local
addr, local port, remote addr, remote port). SO_REUSEADDR just says
that you can reuse local addresses. The 5 tuple still must be
unique!" by Michael Hunter (mphunter#qnx.com). This is true, and this
is why it is very unlikely that unexpected data will ever be seen by
your server. The danger is that such a 5 tuple is still floating
around on the net, and while it is bouncing around, a new connection
from the same client, on the same system, happens to get the same
remote port. This is explained by Richard Stevens in ``2.7 Please
explain the TIME_WAIT state.''.
You have a process that is already using that port. netstat -tulpn will enable one to find the process ID of that is using a particular port.
Address already in use means that the port you are trying to allocate for your current execution is already occupied/allocated to some other process.
If you are a developer and if you are working on an application which require lots of testing, you might have an instance of your same application running in background (may be you forgot to stop it properly)
So if you encounter this error, just see which application/process is using the port.
In linux try using netstat -tulpn. This command will list down a process list with all running processes.
Check if an application is using your port. If that application or process is another important one then you might want to use another port which is not used by any process/application.
Anyway you can stop the process which uses your port and let your application take it.
If you are in linux environment try,
Use netstat -tulpn to display the processes
kill <pid> This will terminate the process
If you are using windows,
Use netstat -a -o -n to check for the port usages
Use taskkill /F /PID <pid> to kill that process
The error usually means that the port you are trying to open is being already used by another application. Try using netstat to see which ports are open and then use an available port.
Also check if you are binding to the right ip address (I am assuming it would be localhost)
if address is already in use can you just want to kill whoso ever process is using the port, you can use
lsof -ti:PortNumberGoesHere | xargs kill -9
source and inspiration this.
PS: Could not use netstat because it not installed already.
As mentioned above the port is in use already.
This could be due to several reasons
some other application is already using it.
The port is in close_wait state when your program is waiting for the other end to close the program.refer (https://unix.stackexchange.com/questions/10106/orphaned-connections-in-close-wait-state).
The program might be in time_wait state. you can wait or use socket option SO_REUSEADDR as mentioned in another post.
Do netstat -a | grep <portno> to check the port state.
It also happens when you have not give enough permissions(read and write) to your sock file!
Just add expected permission to your sock contained folder and your sock file:
chmod ug+rw /path/to/your/
chmod ug+rw /path/to/your/file.sock
Then have fun!
I was also facing that problem, but I resolved it.
Make sure that both the programs for client-side and server-side are on different projects in your IDE, in my case NetBeans. Then assuming you're using localhost, I recommend you to implement both the programs as two different projects.
To terminate all node processes:
killall -9 node
First of check which port are listening,
netstat -tlpn
then select available port to conect,
sudo netstat -tlpn | grep ':port'
Fix it into also to your server and clients interfaces. Go Barrier tab -> change settings, -> port value type -> save/ok
Check both clients and server have similar port values
Then Reload.
Now it should be ok.
Check for running process pid:
pidof <process-name>
Kill processes:
sudo kill -9 process_id_1 process_id_2 process_id_3

Resources