0

I would like my web server to refuse to answer queries to a domain name. In Iptables I have added to my iptables file:

-A INPUT -p tcp --dport 80 -m string --string "Host: mydomain.example" --algo bm -j REJECT

However, no rejection packet is received. I get a timeout from the client side. I would like the other end to be aware that the web server blocks this domain.

on the client side, right now I get:

MacBook-Pro-de-nicolas:~ nicolasguerinet$ curl mydomain.example
curl: (56) Recv failure: Operation timed out

I would like a "connection refused" error.

Patrick Mevzek
  • 9,273
  • 7
  • 29
  • 42
  • 2
    Do you mean `-j REJECT`? – MadHatter Jul 23 '18 at 07:43
  • So now we turn to your test rig. Is there any kind of firewall between your test client and server? – MadHatter Jul 23 '18 at 08:12
  • there is no firewall on client side and the rule is at the top of the Iptables file on server side. – Nicolas Guérinet Jul 23 '18 at 08:40
  • 1
    There is so much that could still be going wrong with this, and it could take some siginficant time to track it down, because you've not told us the real domain name, nor your client and server network geometry. It could be DNS, split-horizon or not, it could be hairpin NAT, it could be a ton of stuff. Unless you're willing to come clean about all of that, and your full `iptables` ruleset, I think HBruijn's suggestion, to do this at layer 4, is much the best. – MadHatter Jul 23 '18 at 09:07

1 Answers1

3

Posting netfilter ("iptables") firewall rules in isolation makes it difficult to analyse problems since your firewall inspects traffic in the specific order the rules are listed and effective behaviour depends a lot that order.

I think I understand what you're trying to achieve and I also think you're approach is fundamentally flawed, sorry.

  1. Most Linux firewall configurations are stateful and once a connection is allowed all subsequent traffic over that connection is also allowed without further inspection. Since the web browser will only send the HTTP protocol Host: header once the TCP/IP connection has been established, then your rule will never be applicable.

  2. If you do succeed in blocking the TCP packet with the Host: header, that is the only thing that happens. That is not quite enough for "the other end to be aware that the web server blocks this domain", only that the established connection has suddenly been terminated.

A much better solution IMHO is to set up either a virtual host for the domain you wish to block (or set up a default virtual host that handles requests for any and all domain names that are NOT explicitly configured) and set up that virtual host to generate a HTTP error that web browsers will understand. This answer explains how to do that with Apache, but you can do similar in nginx or other web servers.

HBruijn
  • 72,524
  • 21
  • 127
  • 192
  • 1
    "*If you do succeed in blocking the the TCP packet with the Host: header, that is the only thing that happens*" that's not entirely true, at least not with `-j REJECT`: by default, an icmp port-unreachable message will also be sent, and other options are configurable. Nevertheless I agree with your bigger picture answer. – MadHatter Jul 23 '18 at 08:33
  • Agreed @MadHatter , my explanation was a bit too short, my main argument is that that terminating, with whatever response, the established connection is unlikely to give the visitor a clear message that access to a specific domain name is blocked. – HBruijn Jul 23 '18 at 09:41
  • I concur, and I think your answer is better now. I'd upvote it, except I already did, so can't do it again! – MadHatter Jul 23 '18 at 09:43