1

Somebody is sending a bunch of garbage data to port 80 on my Apache server, causing tons of 400 Bad Request errors. There's nothing I can really do about it, unfortunately, but can I at least prevent it from filling up my logs? I can't find a way to filter based on status code in If, SetEnvIf, or mod_rewrite.

chowbok
  • 11
  • 3

3 Answers3

3

In your case, you are wanting to conditional logging based on the response of a query. Most conditional logging, such as by IP or URL path, operates on the request.

Prior to httpd 2.4, you might do something like the following to not log certain requests based on data in the request.

eg.

SetEnvIf Request_URI "^/wpad.dat(.*)$" noise
SetEnvIf Request_URI "^/favicon.ico$" noise

CustomLog access_log combined env=!noise

However, using SetEnvIf is only useful for filtering based on requests. We would need an environment variable (in the Apache httpd sence) that gives us the response code, as CustomLog gets processed at the end of the request.

In httpd 2.4, we also have the more flexible construct of the 'expression', so CustomLog might have either an 'env=xxx', or 'expr=xxx'

From http://httpd.apache.org/docs/current/mod/mod_log_config.html

"The third argument is optional and controls whether or not to log a particular request. The condition can be the presence or absence (in the case of a 'env=!name' clause) of a particular variable in the server environment."

So your question really boils down to: "is there an httpd environment variable that gives me the response code that was generated for a request"

See: Apache environment variables list? and: https://httpd.apache.org/docs/2.4/expr.html#vars

From the documentation itself:

# Conditional logging
CustomLog logs/access-errors.log common "expr=%{REQUEST_STATUS} >= 400"
CustomLog logs/access-errors-specific.log common "expr=%{REQUEST_STATUS} -in {'405','410'}"
Cameron Kerr
  • 4,069
  • 19
  • 25
1

LogLevel will allow you to set what severity of issues you are on the error log. CustomLog will allow you to edit what content is shown in the access log.

See https://httpd.apache.org/docs/1.3/logs.html#errorlog and links therein to find a solution for your exact issue as it's unclear which log you're talking about currently

Conditional Logging There are times when it is convenient to exclude certain entries from the access logs based on characteristics of the client request. This is easily accomplished with the help of environment variables. First, an environment variable must be set to indicate that the request meets certain conditions. This is usually accomplished with SetEnvIf. Then the env= clause of the CustomLog directive is used to include or exclude requests where the environment variable is set. Some examples:

# Mark requests from the loop-back interface:
SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog
# Mark requests for the robots.txt file:
SetEnvIf Request_URI "^/robots\.txt$" dontlog
# Log what remains:
CustomLog logs/access_log common env=!dontlog

As another example, consider logging requests from english-speakers to one log file, and non-english speakers to a different log file.

SetEnvIf Accept-Language "en" english
CustomLog logs/english_log common env=english
CustomLog logs/non_english_log common env=!english

Although we have just shown that conditional logging is very powerful and flexibly, it is not the only way to control the contents of the logs. Log files are more useful when they contain a complete record of server activity. It is often easier to simply post-process the log files to remove requests that you do not want to consider.

LTPCGO
  • 508
  • 1
  • 3
  • 15
  • Neither of those will help me. LogLevel only concerns the ErrorLog, which is not my concern here. CustomLog just controls the fields that are logged, it won't allow me to exclude log lines based on status code. – chowbok Jan 08 '20 at 18:37
  • if you read the full article then it definitely will - with the added clarity I've been able to copy and paste the exact code and examples in question – LTPCGO Jan 08 '20 at 18:46
  • And how do I exclude based on random garbage in the request? – chowbok Jan 09 '20 at 19:20
  • I would block the 400. Or, you have to give us an example of the garbage. If it's literally random then you can't block it based on the content – LTPCGO Jan 09 '20 at 19:44
  • It is literally random, or at least has no discernible pattern. So, like I said, this won't work for me. – chowbok Jan 10 '20 at 00:22
  • How do you expect to have any filter that hasn't got anything pattern? As I said, you need to give us some examples of the garbage. You could also block 400s altogether which was your original question – LTPCGO Jan 10 '20 at 00:29
0

Try temporarily add a rule in your iptables to drop any requests incoming from that IP address. Maybe its some script kiddie playing around. But would strongly recommend using firewalls for preventing such things before they reaching your webserver, something like ufw or intrusion detection systems like snort.

Dave M
  • 4,514
  • 22
  • 31
  • 30
Fsoc
  • 83
  • 4
  • This really doesn't answer my question. I can't block by IP. I just want to prevent logging the requests. – chowbok Jan 04 '20 at 16:46
  • Add Intrusion detection system to your server, it blocks any suspicious requests. – Fsoc Jan 04 '20 at 16:48