Securing the default Website
We have a fairly secure default website to filter out some of the noise, for example we don't bother with http any more and anyone that is using http now really should be looking at getting a different browser. While we do drop port 80 at the edge router and the Pfsense firewall it seems best to also drop it at the reverse proxy as well even, though no one should be able to get to the reverse proxy by port 80 in any case a defence in depth is the best idea. We have included some of the commented out options for completeness including a permanent redirect for 80 that as already stated should never actually be reached.
We do use Cloudflare's proxy service to filter out a lot of the fluff and malicious clients because they are better placed than us to do that sort of filtering. We assume that there will be lots of web crawlers that will do port scans of any and all IP addresses in a random order so we do not want any confirmation that our IP address has anything on the end of it and so it is better to drop unknown traffic and not give a closed response. To help with the filtering of the bots and crawlers we drop any incoming web traffic on 443 that does not come from Cloudflare. Unfortunately, the edge router does not have a lot of granularity in it's rules so it forwards all 443 directly to the Pfsense firewall and this does have options to specify the source so it drops anything on 443 that does not come from Cloudflare's IP addresses.
The default website definition is like this:
# --- 1. PORT 80 (Keep the Redirect) ---
# We keep this so your own browser automatically fixes "http" typos.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# reset the connection attempt
return 444;
#redirect to the https with the same server and page
# return 301 https://$host$request_uri;
}
# --- 2. PORT 443 (The Silent Treatment) ---
# If someone hits your IP or an unknown domain via HTTPS,
# we kill the connection instantly.
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name _;
ssl_certificate /etc/ssl/certs/seaoffatenet.crt;
ssl_certificate_key /etc/ssl/private/seaoffatenet.key;
ssl_reject_handshake on;
# The "Drop" Command
return 444;
}
# the alternative is to redirect the unknowns to www.seaoffate.net
# --- 2. THE PORT 443 CATCH-ALL ---
# This catches any HTTPS request that doesn't match your known apps.
# (e.g. your raw IP address or unknown subdomains)
#server {
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
# server_name _;
# # Cloudflare Origin Certs
# ssl_certificate /etc/ssl/certs/seaoffatenet.crt;
# ssl_certificate_key /etc/ssl/private/seaoffatenet.key;
# # Funnel all "Stranger" traffic to your main domain
# # 301 is permanent move and the $request_uri is the get string
# return 301 https://www.seaoffate.net$request_uri;
#}
The Silent Sentry: Engineering a "Black Hole" Default Server
The purpose of this chapter is to detail the final, most aggressive layer of the "Sea of Fate" edge security architecture. When managing a server exposed to the public internet, such as our Nginx gateway "Raisin," you are constantly subjected to "background radiation"—a never-ending stream of automated scans, malicious bots, and script kiddies. These entities do not typically arrive at our doorstep via a clean domain name like notes.seaoffate.net. Instead, they crawl the web by hitting raw IP addresses or brute-forcing subdomains. By configuring a "Default Server" block that specifically targets these unknown requests, we implement a "Black Hole" strategy. This ensures that any traffic not explicitly intended for a known application is neutralized before it can consume system resources or leak information about our internal network.
The Logic of the default_server
In Nginx, the default_server directive is a catch-all flag. If a request arrives and the Host header provided by the browser does not match any of our defined server_name blocks, Nginx defaults to the block marked with this flag. Without a dedicated default block, Nginx will simply serve the first configuration file it finds in alphabetical order. In a home lab environment, this is a significant security risk; it means an anonymous scanner hitting our IP address might accidentally be served our BookStack login page or our private Dashy dashboard. By creating a specific "Stranger" block, we take control of the "unmatched" traffic and decide exactly how the server should behave when faced with the unknown.
The Port 80 "Silent Reset"
The first component of our global-redirect.conf handles the legacy Port 80. While our pfSense router likely blocks this port at the hardware level, maintaining this block on Nginx is a vital "Defense in Depth" measure. If a misconfiguration occurs on the router or an internal device tries to reach the gateway via HTTP, Nginx must have a programmed response.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
The use of return 444; is a sophisticated tactical choice. Unlike standard HTTP codes like 403 Forbidden (which tells the attacker "You aren't allowed here") or 404 Not Found (which tells them "This page doesn't exist"), the 444 status code is a non-standard Nginx instruction that tells the server to close the connection immediately. It sends no headers, no "Server: nginx" identifier, and no body data. To the requester, it appears as though the connection was simply "reset" or the server timed out. This saves bandwidth, hides the identity of our web server, and provides zero feedback to an attacker trying to map our network.
The Port 443 "Handshake Rejection"
Securing Port 443 is a more complex challenge because of the SSL/TLS handshake. Normally, for Nginx to "read" the domain name in the request, it must first complete the encryption handshake. This is a point of vulnerability; if Nginx completes the handshake using our seaoffate.net certificate for a "Stranger" request, it has already leaked our domain name and our certificate provider's details to a potentially malicious scanner.
To prevent this, you have implemented ssl_reject_handshake on;. This directive, introduced in modern Nginx versions, allows the server to terminate the connection during the handshake process if the incoming Server Name Indication (SNI) does not match a valid, known host. By combining this with return 444;, you ensure that "Raisin" remains a digital ghost. An attacker hitting our IP over HTTPS will see an "SSL Handshake Failed" error, which is indistinguishable from a server that simply doesn't support HTTPS or a broken network link. This is the pinnacle of the "Silent Treatment."
Why We Commented Out the 301 Redirect
In our configuration, there is a commented-out block that would otherwise funnel all "Stranger" traffic to https://www.seaoffate.net. While a 301 Moved Permanently redirect is a standard tool for SEO and user experience, it was intentionally discarded in this "Super Secure" configuration for several critical reasons involving the philosophy of Hardened Defense.
First, a 301 Redirect is an "Information Leak." When you issue a 301 redirect, you are confirming to the requester that a server exists at this IP address, that it is running Nginx, and that it is the owner of the seaoffate.net domain. For a friend who mistypes a URL, this is helpful; for a botnet searching for targets, this is a confirmed "hit." By choosing 444 over 301, you choose invisibility over helpfulness. In the context of "Plum" and our private notes, the security of the data outweighs the convenience of an automatic redirect for unknown subdomains.
Second, the 301 Redirect creates unnecessary overhead. To process a redirect, Nginx must accept the connection, parse the request, generate an HTTP response header, and send that data back across the wire. While the CPU cost for a single request is negligible, during a concentrated bot attack or a "denial of service" event, thousands of these redirects can consume system memory and log-file space. The 444 drop is the most "resource-cheap" way to handle an attack; it discards the packet at the earliest possible stage, preserving "Raisin's" resources for legitimate traffic destined for BookStack.
Finally, the 301 Redirect can bypass firewall logic. If you redirect an unknown subdomain to our main site, you are essentially "inviting" the stranger to our front door. If our landing page has a vulnerability, you have just helped the attacker find it. By using the "Silent Treatment," you enforce a strict "Know our Target" policy. If the requester doesn't know exactly which subdomain they are looking for, they are simply disconnected. This prevents "Discovery Attacks" where an attacker tries dev.seaoffate.net, test.seaoffate.net, or admin.seaoffate.net just to see what responds.
Summary: The Philosophy of the Black Hole
By implementing this "Catch-All" block and favoring the 444 drop over the 301 redirect, we have moved beyond "Standard Security" into "Hostile Environment Hardening." You are treating the public internet as an inherently untrusted space. The server "Raisin" is no longer a helpful librarian trying to guide people to the right page; it is a fortified bunker that only opens its doors to those who have the correct, specific "password"—which, in this case, is the exact domain name notes.seaoffate.net.
This chapter serves as a reminder that silence is a security feature. By commenting out the redirect, you have prioritized the "Defense in Depth" of our internal Plum server over the convenience of the public web. We have ensured that even if a scanner manages to bypass our pfSense router, it will find nothing but a closed door and a silent connection at the Nginx gateway.
Logic Comparison: 301 vs. 444
| Feature | 301 Redirect (Helpful) | 444 Drop (Hardened) |
| Response | "Please go to the main site." | Silence. |
| Identity | Confirms server existence and domain. | Hides server identity entirely. |
| Resource Use | High (Full HTTP response cycle). | Zero (Immediate socket closure). |
| User Experience | Good for lost humans. | Frustrating for bots (Success!). |
| Information Leak | Discloses Nginx version and SNI. | Discloses nothing. |
The Digital Void: Engineering the "Silent Treatment" for Edge Security
In the previous chapters, we established the "Chain of Trust" that allows legitimate traffic to flow from the public internet, through Cloudflare, into our Nginx gateway "Raisin," and ultimately to the "Plum" server. However, a professional-grade architecture must be as concerned with what it excludes as with what it includes. The public-facing edge of any network is essentially a lighthouse in a storm, attracting not only the ships you wish to guide but also an endless barrage of automated scanners, credential stuffers, and "Internet Census" bots. To handle this, we implement a "Catch-All" or "Default Server" strategy. The configuration block for Port 443 presented here represents a departure from standard, helpful web serving and moves into the realm of aggressive defensive engineering. By choosing the "Silent Treatment" over the traditional "Helpful Redirect," we are making a calculated decision to prioritize security and resource preservation over the convenience of unknown or accidental visitors.
The Logic of the Default Server and the _ Hostname
To understand the specific code block, one must first grasp how Nginx decides which "Server Block" handles an incoming request. When a packet arrives at "Raisin" on Port 443, Nginx looks at the HTTP Host header (or the SNI during the TLS handshake) and compares it against the server_name directives in all available configuration files. If you have a block for notes.seaoffate.net, and the request matches that name, Nginx routes the traffic there. However, if a bot hits your raw IP address (e.g., https://123.123.123.123) or a non-existent subdomain (e.g., https://random-test.seaoffate.net), there is no direct match. Without a designated default_server, Nginx will simply pick the first loaded configuration file alphabetically and serve that site. This is a catastrophic security failure; it means your private BookStack instance could accidentally be served to an anonymous scanner simply because its filename started with "B."
By using listen 443 ssl default_server; and server_name _;, we are creating a "Security Net." The underscore is a catch-all name that never matches a real domain, and the default_server flag ensures that this specific block is the one that catches every single piece of "unmatched" traffic. This block becomes the definitive authority for the unknown. It is the "garbage disposal" of your web server, and the instructions we give it determine how much information we leak to the outside world.
The Mechanics of ssl_reject_handshake on
One of the most sophisticated lines in this configuration is ssl_reject_handshake on;. In traditional HTTPS serving, a server must complete the TLS handshake before it can even see what domain the user is asking for. To complete that handshake, the server must present a certificate. If you present your seaoffate.net certificate to an anonymous IP scanner, you have already lost a piece of the battle. You have confirmed to the scanner that this IP address belongs to your domain, and you have provided them with your Certificate Authority’s details and your public key. Even if you block them later, they have already indexed your IP-to-Domain relationship.
The ssl_reject_handshake directive, introduced in modern Nginx versions, changes this dynamic entirely. It allows Nginx to terminate the connection during the initial TLS "Client Hello" if the requested Server Name Indication (SNI) does not match a known, configured server block. By including this in our default block, we ensure that if a scanner hits the raw IP or an unknown name, Nginx refuses to even show them a certificate. The connection is severed before any cryptographic "ID cards" are exchanged. This is a powerful deterrent against mass-scanning services like Shodan or Censys, as it prevents your home IP from being easily associated with your private services in their public databases.
The Power of the 444 Return Code
Once the request is caught by this default block, we use the command return 444;. While most people are familiar with the standard 403 Forbidden or 404 Not Found codes, the 444 code is a non-standard Nginx-specific status that instructs the server to close the connection immediately without sending any response to the client.
Standard error codes require Nginx to generate an HTTP header, specify a content type, and send a payload (even if it is just a small "403" page). This uses CPU cycles and network bandwidth. More importantly, it confirms the existence of a web server. If an attacker receives a 403 Forbidden, they know they found a wall, and they might start looking for a way over it. If they receive a 444, their connection simply "drops." To the attacker’s software, it looks like the server crashed, the network is down, or the IP is dead. This "Black Hole" effect is the ultimate goal of the Silent Treatment. It forces the attacker to move on to a more "talkative" target, preserving your system resources for legitimate users.
Analyzing the Commented-Out Alternative: The 301 Redirect
In the provided configuration, there is a second, commented-out block that proposes an alternative: redirecting all unknown traffic to https://www.seaoffate.net. This is the "Helpful" approach. A 301 Moved Permanently redirect tells the browser (and the user) that they have reached the right server but the wrong address, and it kindly pushes them toward the main landing page. While this is common practice for public-facing commercial websites, we have explicitly chosen not to do this for several high-level architectural reasons.
1. Preventing Information Leaks (The Reconnaissance Phase)
A 301 redirect is a goldmine for reconnaissance. When Nginx issues a 301, it must send a valid HTTP response. This response often includes headers that identify the server as "nginx," and sometimes even discloses the specific version. Furthermore, by redirecting a stranger to your main domain, you are confirming: "Yes, this IP address is the host for Sea of Fate." You have essentially validated the attacker's search. In our "Silent Treatment" model, we operate on the principle of "Security through Obscurity" as a secondary layer; if the requester doesn't know the exact "Secret Knock" (notes.seaoffate.net), we don't even admit that we are a web server.
2. Avoiding "Host Header Injection" and Log Poisoning
Redirecting based on the $host or $request_uri can be risky if not handled perfectly. If an attacker sends a malicious hostname, and your server reflects that back in a 301 redirect, you could potentially be used in a "Reflected" attack or find your own logs filled with thousands of entries of redirected garbage traffic. By choosing to return 444, we keep our log files clean. We don't log the "Stranger" traffic because we don't even process it as a full HTTP request. This keeps the logs for "Plum" and "Raisin" focused only on legitimate traffic, making it much easier to spot actual security threats.
3. Resource Preservation during Volumetric Attacks
In the event of a botnet "storm"—where thousands of bots hit your IP address per second—the difference between a 301 and a 444 is significant. To issue a 301, Nginx has to do a lot of work: accept the TCP connection, perform the SSL handshake (which is computationally expensive), parse the HTTP request, and then send a response. During an attack, this can spike your CPU usage and saturate your upload bandwidth. By contrast, the "Silent Treatment" (especially with ssl_reject_handshake) drops the packet at the earliest possible microsecond. It is the most "computationally cheap" way to handle an enemy. It allows your server to remain responsive for your private BookStack notes even while a botnet is banging on the front door.
The Philosophical Stance: Defense in Depth
The decision to use the 444 drop instead of the 301 redirect represents a philosophical commitment to Defense in Depth. It acknowledges that your pfSense router and edge firewall might have allowed the packet through, but it refuses to let that packet interact with the application layer. It treats the internet as a hostile environment where "helpfulness" to strangers is a liability.
In your specific network, where "Plum" holds private data and "Raisin" acts as the sole guardian, this "Silent Treatment" ensures that:
-
IP Scanners find a "dead" IP.
-
Credential Stuffers can't even find a login page to attack.
-
Internal Errors (like a misconfigured subdomain) don't accidentally expose your internal directory structure.
Conclusion for the Installation Guide
For the reader of these notes, this section serves as a warning: Do not be tempted by the "Helpful Redirect." While it might seem professional to guide a lost user back to your main website, the reality of modern network security is that 99.9% of "lost users" hitting your IP directly are not humans—they are automated threats. By implementing the 444 "Black Hole" and the ssl_reject_handshake directive, you are turning "Raisin" into a hardened, invisible sentinel. You are ensuring that your private logic—your BookStack, your Dashy, and your personal configs—remains cloaked in silence, accessible only to those who have the correct, encrypted map. Another way of seeing the lost users is that if it is indeed a real person they will see the error message and type in the correct DNS name.
Logic Comparison Table
| Feature | The "Silent Treatment" (444) | The "Helpful Redirect" (301) |
| Visibility | Acts as a "Dead IP." | Confirms server presence. |
| SSL Handshake | Rejected (Zero info leaked). | Completed (Domain info leaked). |
| CPU Usage | Negligible. | Moderate (per request). |
| Bot Resistance | High (Frustrates scanners). | Low (Validates scanners). |
| Information Disclosure | None. | Discloses Domain and Server Type. |
| Best Use Case | Private Home Lab / High Security. | Public Commercial Website. |
Verification and Vigilance: Auditing the "Digital Void" via Nginx Logs
The final component of implementing a "Silent Treatment" security policy is the verification of its effectiveness. In systems administration, a configuration is only as good as its audit trail; without visibility into how the server is handling rejected traffic, we are essentially flying blind. By monitoring the Nginx logs on "Raisin," we can confirm that the 444 connection drops and ssl_reject_handshake directives are functioning as intended. Furthermore, we must address the human element: the "Real Person" vs. the "Bot." As you correctly noted, the beauty of this hardened approach is that it acts as a filter that only humans can bypass through cognitive correction. While a bot will simply record a failed connection and move on, a legitimate user who makes a typo will see a connection error, realize their mistake, and re-type the correct DNS name.
The Human Logic: Typos vs. Reconnaissance
When a human user attempts to reach notes.seaoffate.net but accidentally types an incorrect subdomain or attempts to hit the IP address directly, they are met with a "Connection Reset" or "Secure Connection Failed" message. In a traditional "Helpful" setup, a 301 redirect would fix this for them automatically. However, by removing that safety net, we are employing a form of "Behavioral Authentication."
A real person has the context and the intent to reach your specific service. When they see a failure, they check the URL bar, identify the typo, and correct it to the valid notes.seaoffate.net address. This manual correction is a hurdle that automated scanners do not jump. Bots are programmed for efficiency; they hit thousands of IPs per minute, and if an IP doesn't respond with a valid web page or a redirect, it is marked as "dead" or "uninteresting" and discarded from the active target list. By forcing this manual correction, you ensure that only those with the "Secret Knock" (the correct DNS name) ever gain access to the logic sitting on "Plum."
Locating the Evidence: The Nginx Error and Access Logs
To see this system in action, we must look at the logs on "Raisin." Because we are using the 444 return code, the behavior in the logs is slightly different than standard traffic. Standard successful traffic is recorded in the access.log, while errors and rejections are typically found in the error.log.
1. Identifying Handshake Rejections
When the ssl_reject_handshake on; directive triggers, it happens before a full HTTP request is even formed. Therefore, you will not see these attempts in your access.log. Instead, you must look at the error.log. You can search for these events using grep:
sudo grep "SSL_do_handshake() failed" /var/log/nginx/error.log
You will see entries similar to this:
2026/02/28 09:00:01 [info] 1234#0: *5678 SSL_do_handshake() failed (SSL: error:0A000458:SSL routines::tlsv1 unrecognized name) while SSL handshaking, client: 192.0.2.1, server: 0.0.0.0:443
The key phrase here is "unrecognized name." This is the smoking gun that proves a requester tried to connect to your IP or an unknown subdomain, and Nginx successfully slammed the door during the handshake because the name didn't match your allowed list.
2. Auditing the 444 Drops
Because 444 is an Nginx-internal code that closes the connection without a response, it often appears in the access.log with a status of 444 and 0 bytes sent. You can monitor these in real-time to see the "Background Radiation" of the internet hitting your server:
sudo tail -f /var/log/nginx/access.log | awk '$9 == 444'
If you see a flurry of these, do not be alarmed. It simply means your "Black Hole" is working. Each line represents a bot that found nothing, received nothing, and was forced to move on.
The Danger of "Log Bloat"
One reason we prefer the 444 drop over a 301 redirect is to prevent our logs from becoming useless. If you redirect every bot, your access.log will be filled with thousands of 301 entries, making it nearly impossible to find the legitimate traffic for "Plum." By using return 444;, many administrators choose to turn off logging for the default server block entirely to save disk space and reduce "noise."
If you want to keep your logs clean, you can add access_log off; to your default server block. This effectively makes the "Stranger" traffic invisible even to you. However, during the initial setup of a server like "Raisin," it is wise to keep logging enabled for a few weeks. This allows you to verify that you haven't accidentally blocked a legitimate service or a secondary domain you forgot you owned.
Interpreting the Patterns: Who is Knocking?
As you monitor these logs, you will begin to notice patterns. You will see "User-Agents" that claim to be common browsers but are hitting your IP on strange ports, or requests for files like /wp-admin.php or /.env. These are classic automated vulnerability scans.
By seeing these in the context of a 444 drop, you gain a sense of security. You are watching the "bullets" hit the "armor." The scanner is looking for a specific vulnerability in WordPress or a leaked environment file, but because it couldn't even complete a handshake or receive a basic 200 OK response, it never even got to ask for those files. The attack died in the "Void" you created.
Summary: The Audit as a Security Posture
Checking the logs is the final step in the "Super Secure" installation of BookStack on Plum. It completes the cycle of Prevention, Detection, and Verification.
-
Prevention: You configured the
444andssl_reject_handshake. -
Detection: The logs record the attempts.
-
Verification: You review the logs to ensure no legitimate users are being caught in the net.
For your installation book, this section serves as the "Closing Argument." It proves that the "Silent Treatment" is not just a theoretical preference but a functional, measurable barrier. It turns your server from a passive target into an active, silent sentinel that ignores the noise of the internet and only speaks when spoken to correctly. You have successfully engineered a system where a human’s "typo" is a minor inconvenience, but a bot’s "scan" is a total dead end.
Verification Cheat Sheet
| Task | Command | Expected Result |
| Check Handshake Rejections | grep "unrecognized name" error.log |
List of IPs that failed the SNI check. |
| Monitor 444 Drops | `tail -f access.log | grep 444` |
| Verify Successful Notes Traffic | grep "notes.seaoffate.net" access.log |
List of 200 OK responses for legitimate users. |
| Check for "Log Poisoning" | `awk '{print $1}' access.log | sort |
No comments to display
No comments to display