A word of warning guys, I've had a look through the code and unless I've missed the obvious, there's nothing in there to change user ID; which means this would either need to be run as root, or would need to listen on a port > 1024.
In the case of the former, that's a huge step backwards in terms of security.
In the case of the latter, that would mean you'd need another reverse proxy hooked up - which would negate the need for this web server to begin with.
This can easily be fixed within Go though:
import (
"log"
"syscall"
)
const (
user_id int = 1000
group_id int = 1000
)
func secureDaemon() {
// set group id first as you need to be root to change group
err := syscall.Setgid(group_id)
if err != nil {
log.Fatalln(err)
}
err = syscall.Setuid(user_id)
if err != nil {
log.Fatalln(err)
}
}
You can also add chroot to your code if you want to be ultra paranoid:
This will need to be done before you change your user ID (as you need root permissions to chroot) and you may need to compile the Go without CGO because some of the standard Go libraries will have SO dependencies (I found this to be the case with domain name lookups).
(the above code is adapted from my own Go web framework that I'm in the processes of building)
yeah I saw it, thanks so much. I like this kind of single-purpose small libraries. The only thing is, I hesitate to depend on other people's repositories since they may get moved or change the API.
WARNING: I implemented a tiny library for that in go a while ago. Go under Linux is not safe! Linux is not posix compliant and only sets the IDs for the current thread. Go almost always spawned more threads before initializing your code which are then still owned by root and are in the threadpool for your goroutines:
I'm guessing it might depend on the point in your Go code whrn you setuid as the tests that I did on my own project, setuid changed the user id as expacted then the processes were spawned.
However you have given me reason to test my own code again and more thoroughly :-)
Indeed, but it would make more sense (in my opinion) to have the web server natively 'de-elevate' it's permissions than to expect the sysadmin to be competent enough to set up authbind manually. Particularly when setuid/setgid is so easy in Go and that every other webserver out there natively drops down to a designated webuser after the daemons been launched and ports binded.
It's easy enough to run this as a non-root user and use your local software firewall port to forward port 80 inbound to whatever high port this server is listening on.
Indeed, but that doesn't change the fact that it makes more sense having that functionality in the web server itself given its a standard and expected function in all web servers.
I tend not to sign up to many cloud based solutions as I prefer to host my own solutions (partly out of paranoia and partly because I have the server capacity to run my own solutions so it seems to make sense to use my servers where I can).
With github, it's very rare when I have anything worth contributing to other peoples gits so I've never really missed it. But I'm sure I'll end up on there at some point in the future.
In the case of the former, that's a huge step backwards in terms of security.
In the case of the latter, that would mean you'd need another reverse proxy hooked up - which would negate the need for this web server to begin with.
This can easily be fixed within Go though:
You can also add chroot to your code if you want to be ultra paranoid: This will need to be done before you change your user ID (as you need root permissions to chroot) and you may need to compile the Go without CGO because some of the standard Go libraries will have SO dependencies (I found this to be the case with domain name lookups).(the above code is adapted from my own Go web framework that I'm in the processes of building)