0% прочитано

The First Night After Enabling ICanUp Protection: What Real Nginx and Fail2ban Logs Showed

After enabling scanner protection, I left ICanUp running overnight and reviewed the real logs in the morning. The protection worked, Fail2ban banned real addresses, and the review also exposed a DEV gap for nested sensitive paths.

12 жовтня 2026 р. 9 хв читанняNginx

This is the third part of a small practical story about protecting ICanUp.

It started with an analysis of traffic that looked human but behaved like a bot. Then I documented the protection of Laravel sensitive paths with Nginx and Fail2ban.

The next question was the most interesting one: what would the protection show outside a controlled check, after a night of real server traffic?

I did not add anything new before this review. I simply left the server running and checked the actual Nginx and Fail2ban logs in the morning.

This article is not a setup guide. It contains only the first-night results, log analysis, the gap discovered afterward, and conclusions from real operation.

What I Wanted to Verify After Deployment

The controlled checks had already shown that the rules reacted to sensitive paths.

Real production traffic answers different questions:

  • do these requests arrive without my own test traffic;
  • does Nginx actually return the expected 403;
  • does Fail2ban see those events in the real log;
  • do detections accumulate into real bans;
  • does live traffic reveal cases that the original verification did not cover.

Real Requests for Sensitive Paths Appeared in the Logs

A shortened and anonymized example of what appeared in Nginx
GET /.env        -> 403GET /.git/config -> 403GET /...         -> 403

The logs confirmed that external clients were actually requesting /.env, /.git/config, and similar paths.

Nginx stopped those requests with 403, so they did not continue as ordinary application traffic.

The First Review Showed 13 Detections and 5 Bans

Actual state at the time of the morning review
Fail2ban filter hits: 13 Total bans: 5 Test bans: 2Real bans: 3 Real IPs still banned: 3Ban duration: 24 hours At least one real banhappened overnight.

At the time of the review, Fail2ban had recorded 13 filter detections and 5 bans in total.

Two bans came from my own test checks. Three came from real external traffic.

All three real addresses were still banned for 24 hours, and one of those bans happened during the night itself.

I intentionally do not publish the IP addresses. The useful part is the system behavior, not the specific addresses.

The Numbers Confirmed the Full Nginx -> Log -> Fail2ban -> Ban Chain

The result confirmed the whole operational flow, not just one regex
scanner request      |      vNginx matchessensitive path      |      v403 response      |      vrequest appearsin log      |      vFail2ban detects it      |

This mattered more to me than one successful manual test.

The full sequence was confirmed: Nginx recognizes the request, returns 403, the event appears in the log, Fail2ban detects it, and after the required number of detections the address is banned.

The protection therefore did not merely look correct in configuration. It operated on traffic that arrived without my involvement.

Thirteen Detections Do Not Mean Thirteen Banned Addresses

A filter hit means an event matched the pattern. A ban means a specific address satisfied the conditions for blocking.

I therefore read these metrics separately: detections show suspicious activity, while bans show how many sources actually crossed the configured threshold.

The Review Also Exposed a DEV Gap

The gap affected nested path variants on DEV
production /.env/app/.env/.../.env blocked bysensitive-path protection  DEV before the fix /.env   -> blocked /app/.env

During the additional review I found that production protection was working, while DEV still had a gap for nested paths such as /app/.env.

Such a request could reach the proxy instead of being stopped by the same protection rule.

The gap was later fixed and verified separately. I am not covering that implementation here because the important operational lesson is broader: live verification can expose differences between environments.

A Successful Result and a Discovered Gap Can Both Be True

It would be wrong to say either "the protection worked, therefore everything is perfect" or "a DEV gap existed, therefore the protection did not work."

The facts were more precise: production rules were genuinely stopping scanner requests and Fail2ban was genuinely banning sources. At the same time, the review exposed a separate DEV inconsistency.

That is exactly what makes this useful as Build in Public: not only showing a successful release, but also showing what became visible after it went live.

What the First Night Does Not Prove

These results do not mean the server is now fully protected.

  • They do not prove that the application has no other vulnerabilities.
  • They do not prove that every possible scanner path is already covered.
  • Fail2ban is not complete DDoS protection.
  • Application-level authorization and other security boundaries remain separate layers.
  • One successful day does not replace continued log review.

Real Logs Added More Than Another Manual Test

A controlled check and real traffic answer different questions
controlled check known pathknown timeknown sourceknown expected result  real traffic unknown sourceunknown timingreal scanner behaviorreal ban lifecycleenvironment differences

A manual test request is useful for checking one expected result.

A night of real traffic showed something different: these requests really arrive, the ban lifecycle starts without my involvement, and different environments may not behave identically.

For security changes I therefore treat post-release observation as its own verification stage.

For Build in Public, the Day After Release Matters Too

It is easy to publish an article at the moment a feature is finished and every controlled check is green.

It is more useful to return after real operation and answer a second question: what happened next?

In this case the answer is valuable precisely because it is not idealized: the protection genuinely worked, real bans occurred, and the review still found another gap that the original scenario had not exposed.

What I Took Away from the First Night

My conclusions from the morning review:

  • Scanner traffic was not theoretical. Requests for sensitive paths arrived in real traffic.
  • Nginx protection acted before the application layer. Known sensitive paths showed 403 in the logs.
  • Fail2ban worked on the real event stream. There was a real overnight ban, not only test bans.
  • Filter hits and bans should be read as separate metrics.
  • Every environment needs verification. The nested-path DEV gap exposed a separate problem.
  • Security deployment should be followed by observation. The real logs provided the most useful feedback.

Real Traffic Confirmed the Protection and Challenged It at the Same Time

After the first night I got exactly the kind of result I wanted from leaving the protection alone under real traffic.

Nginx genuinely returned 403 for scanner requests. Fail2ban genuinely accumulated detections and banned addresses. At the time of review there were 13 filter hits, 5 total bans, 2 test bans, and 3 real bans.

At the same time, the analysis exposed a DEV gap for nested sensitive paths that was later fixed and verified.

For me that is stronger evidence than "the test passed": the system proved useful under real traffic and immediately produced the next concrete signal for improvement.

A security change becomes much more informative after deployment: real traffic shows what actually works and what still escaped the original checks.