What’s bunkerized-nginx and why I need it ?
The vast majority of applications served to clients nowadays are in fact web services. Even mobile apps are using web services because, behind the hood, they call external APIs. Even if these web services are heterogeneous in terms of languages or technologies they all share a common factor : the good old HTTP protocol. It has evolved a lot since the 90s to become a complex protocol with many features like WebSocket or multiplexing. Since the web services are in front of the clients, they are the first elements prone to attacks. They are also strategic for hackers because they are directly related to clients and often connected to a database. That’s why we need to protect them despite the complexity and the heterogeneous subsystems.
This is exactly the goal of bunkerized-nginx : applying all the security best practices to any web services without the hassle of doing it manually. It provides a minimal and generic “security by default” against common threats without (much) configuration. But it’s also highly customizable with very detailed settings for specific needs. As of today, bunkerized-nginx comes as a Docker image to make integration with existing systems easier.
What are the main features ?
HTTPS is now a de facto standard and that’s a good thing. It ensures the confidentiality and integrity of the data exchanged and even mutual authentication (although only server authentication is done for the vast majority of web services). Since the existence of Let’s Encrypt, standard certificates are free of charge : there is no reason to not support HTTPS !
Bunkerized-nginx provides Let’s Encrypt automation, the certificates generation and renewal are automatically done without any further action. You can also import your own certificates (e.g. : issued from private internal CA, Extended Validation certificates, …) if needed. Using HTTPS is not enough, the underlying protocol called TLS (Transport Layer Security) needs also some settings in order to strengthen the cryptography. Bunkerized-nginx also does it for you and the result is a A+ grade on SSL Server Test tool :
HTTP messages, whether they come from clients or servers, are composed of two parts : headers and data. When sent from clients the data part is filled with the values of forms (e.g. : login, password, text, file, …) and when sent from server the data part contains the resource asked by the client (e.g. : web page, CSS, JS, image, …). Although the headers part doesn’t contain real data it’s still very important because they can control the way clients and servers are communicating. Things like cache, cookies, compression or even security are controlled by headers.
Bunkerized-nginx comes with state-of-the-art security (and even “standard”) headers without any (much) configuration. As an example, let’s have a look at these particular headers :
- Strict-Transport-Security : tells the clients to always use HTTPS when accessing the web service
- Permissions-Policy : defines the permissions that a web service can use (e.g. : webcam, fullscreen, geolocation, …), if it’s not present the client won’t allow it (to protect in case of a compromise of the web service)
- Server or X-Powered-By : these headers contains information like version number that can be used by hackers to find vulnerabilities, bunkerized-nginx automatically removes them
This list is not exhaustive and some headers, like Content-Security-Policy, still need some further settings depending on your web service. The result is a A+ on the SecurityHeaders tool :
Web Application Firewall (WAF)
When attackers exploit a vulnerability they need to inject some “bad code” inside the HTTP requests. In case of data leak, the leaked data will be inside the HTTP response. A Web Application Firewall (WAF), analyzes both HTTP requests and responses and try to find some “common” patterns used in attacks. If a pattern is found, the corresponding request or response is dropped to prevent its behaviour. It’s like a classical network firewall but for web services (“patterns” are defined in what we call “rules”). The main problem with a WAF is “false positive” (FP) : a rule which is triggered even if there is no attack (i.e. : a legitimate query from a legitimate client is blocked). It will surely need additional settings to remove the FPs but it’s one of the most powerful tool in terms of security. Even if a WAF is not magical and can be bypassed it may slow down an attacker or even better make him choose another target.
ModSecurity is a notorious open-source WAF and is integrated into bunkerized-nginx. Because a WAF without any rules is worth nothing, we also integrated the OWASP Core Rule Set (CRS) that covers the most common attacks used against web services. The CRS includes exclusions rules for popular applications (e.g. : wordpress, nextcloud, drupal, …) and supports custom exclusions rules to remove FPs.
Bad behaviours detection
Attackers leave traces when they try to exploit a vulnerability, use automated tools or gather information. As an example, a common task for hackers is to try to find some “interesting” files or directories on a web site. It works by guessing some “common” paths like /admin, /wp-admin or /secret and we know if they exist or not depending on the status code of the HTTP response (e.g. : 404 – not found, 200 found, …). A “good” user will never generate like dozens of 404 status code in a short period of time. We can use all these traces to deduce that a user is indeed an attacker and block him further access to the web service.
fail2ban is an open-source tool that search for patterns into logs files and do some action if more than X events are found in a period of time. It’s integrated within bunkerized-nginx with a generic rule that search for “strange” HTTP status code (e.g. : 404, 403, 444, …) and ban the corresponding IP address when there is a certain number of match within a period of time.
Bad IP detection
The IP address is one crucial element for any network communication especially on internet because we use “public addresses” that belong to a provider. A public IP address is not enough to uniquely identify someone because it can change from time to time (e.g. : mobile vs home connection, dynamic IP, switch to another ISP, …) and can be “hidden” behind another server (e.g. : TOR, VPN, proxy, …) so it’s not a reliable way to use a whitelist IP approach if you have multiple clients on your web service. We know that real attackers won’t send malicious requests with their own public IP address for obvious anonymous reasons. The IP addresses they will use might be already “known” to be suspicious because they use it in other attacks. If we know it, we can block it before it does any harm on our web service.
Bunkerized-nginx includes several external blacklists to block “known bad IPs” : proxies, TOR, abusers, … It also checks if the IP address is in some DNS Black Listing (DNSBL) that doesn’t need any additional download. Everything (e.g. : enable/disable, download time, DNSBL list, …) is customizable as you want and you can, of course, allow TOR users to visit your web service if you want to.
Bad bot detection
There are plenty of bots scanning/scraping the internet, some of them are good (e.g. : search engines, metadata viewer when posting on social media, …) some are not (e.g. : shodan, hacking tools, …). Some of these bad bots aren’t very technical when they “talk” to a web service, they simply send raw HTTP requests and wait for responses. We may be able to distinguish the “bad” requests from the “good” one with analyzing what differs. But it’s not enough because everything in an HTTP request can be forged since the client has the control over it. When the web service is in fact a website, we can challenge the client to check if it looks like a real web browser with some tricks.
Bunkerized-nginx includes an external blacklist of “bad” user-agent which is an HTTP header used to identify the software used by the client. A user-agent is easily forgeable so we decided to add another mechanism in order to fool automated tools. When enabled, it will send a “challenge” to the client before he can access the whole website. If the challenge is solved then access is granted else access is denied. Some of them are transparent for the “good” users and some are not. At the moment we have 4 types of challenges :
- Cookie : the client must set a specific cookie
- Captcha : the client must solve a captcha
- reCAPATCHA v3 : the client must have a certain score on the transparent reCAPTCHA v3 created by Google
Using this trick can fool some attackers especially the ones with less technical knowledge so they give up and find another target. Here is how some hacking tools react when they are confronted with a challenge :
And much more !
There is much more to say on the features of bunkerized-nginx like :
- Automatic scan of uploaded files with ClamAV
- Docker Swarm support with labels (like Traefik)
- A user-friendly web UI (in beta)
- Easy configuration of major nginx settings
- Custom configuration support
But you should test it by yourself instead of reading this post !
I definitely need it ! What’s next ?