Automatic blocking based on port attempt
-
NOTE: kept getting an "Error: Forbidden" response when trying to submit. Had to remove various bracket/brace/less than/greater than (not sure which it was snagging on) - may be hard to read.
All,
Is there something already in existence for pfSense that provides the ability to logically perform the following:
pass in log quick on interface proto tcp, udp from any to external port port alias list (max-src-states 0, overload BLOCKTABLE flush global)
The purpose is to be able to automatically place invalid connection attempts into a table (that can be pruned via expiretable) where that address is blocked (as src and/or dst) after it attempts connection to some a port (from port-list).
Over the past few weeks have noticed a growing trend in the number of attempts to various ports, with a large percentage being UDP. As a result, being able to block those by way of corresponding rules, earlier in the ruleset:
block log quick on external interface from BLOCKTABLE to any
block log quick on external interface from any to BLOCKTABLEIt avoids the overhead (and added latency) of IDS/IPS, log tail/pfctl calls, etc. as it remains in the confines of PF.
This operates on the premise that if a src address attempts to connect to an aliased list of unused ports - there is very high likelihood that we don't want any interaction with that IP Address for any of the valid, publicly available services. For example, if an external IP Address tries to connect to UDP/500 (isakmp) and we don't offer any IPSec tunnels - then its likely not an IP Address that should be able to [even attempt] access of any of the public facing services.
From a curiosity perspective, toyed with standard f-bsd and PF, this appears to be (at least) accepted by pf:
pass in log quick on EXTERNAL proto tcp, udp from any to (EXTERNAL) port 500 (max 100, source-track rule, max-src-states 0, overload BLOCKIPS flush global)However, pfSense wasn't happy. Copied /tmp/rules.debug to /tmp/rules.test and added the adjusted entry to the end of the file. After repeated attempts of pfctl -nf /tmp/rules.test - It would not accept the rule unless everything in the parenthesis' was removed and was unable to find anything in the GUI that appears to support overload / flush global.
-
@justme2 said in Automatic blocking based on port attempt:
access of any of the public facing services.
And how many of those do you have exactly?
-
Not sure how any number is germane? However, If one considers remote access, VPN, etc. - they are public facing services (external interface), but not for public consumption. Thus, the goal of being able to block source addresses that attempt to connect to non-used protocol/port pairings further increases the ambient protection provided by the firewall. Some installations may actually want a more expansive approach to include common protocol/port pairings (TCP/80, TCP/443 and so on) as a heightened measure - could see this as useful for remote branch where the only traffic should be: VPN, Administrative VPN (backup) and [possibly] source IP limited SSH access. Thus, any other stray [logically] new connection to a TCP and/or UDP port on the external interface should be blocked for some user-specified time interval.
-
Your OVERTHINKING IT!!!
You have services open to the public or you do not.. If your so concerned on what is accessing your "public" services - then lock them down to known source IPs
Thinking that you should block every IP that hits some random port on your IP.. You will be blocking the the vast majority of the internet.. One IP at a time. What you going to do with IPv6?
If your concerned about random ips hitting you, then lock it down to your region with a geoip list..
Logging ever IP that hits some port, and then putting it in a list to block from hitting your IP is just over the top.
Who says this random IP is going to hit some odd ball service first, before it hits your service that is open to the public.. You have fancy script running logging all these ips that hit services, and putting them in a alias.. For what exactly.. Your service that is open to the public is secure it its not secure.. If its open to exploit xyz, -- you should spend more time keeping it up to date vs being worried about some random IP hitting it.
If your worried - then subscribe to some list of bad actor IPs, and block those.
My point about asking how many services you have open to the public - is to get some idea if your some home user with his plex server open, or a cloud provider with users running services behind your IPs, etc. etc..
Either way - just blocking what actually hit your IP is already too late, like I said what if hits your IP that you have a service open on, before it hits a port that you do not.. So its better to just block a known bad actors list than after the fact some random IP hit you.
If you had multiple customers with multiple IPs - with multiple services. Then it might be something to start compiling a list of IPs hitting customer A, before they hit customer B IP, etc.
edit:
So looking at my log this shit IP.. 193.86.95.34 in the last 24 hours has hit me 1989 times.. In all those times hit an open port 3 times, 443.. Guess how many times he actually got through to my service.. ZERO!! Because the service on 443 is openvpn, clearly he didn't have the right key.. So openvpn would hand it over to haproxy.. Guess how many times haproxy passed it through to the server - ZERO.. because it sure and the hell didn't match the sni for my service.. Some port scanner bot.. That is prob on black list somewhere anyway..And again it sure wouldn't get through to my services even if it had the correct sni, etc., because its from the Czech Republic - and only IPs that can get to my services are NA IPs..
So there are many things you can put in place.. before you start logging every random IP, and throwing it into a list of IPs to block.
-
Added to what @johnpoz z said :
Automatic blocking based on port attempt
was already solved a couple of decades ago.
Typically, services that are exposed to 'everybody', like web servers, mail servers, ntp servers etc log incoming connections.
Before anything else, the incoming IP is back resolved to the host name.
For example, an incoming IP says to my mail server "hi, I am mail.gmail.com" but the reverse of the IP says something else :warning: hostname 190.62.pppoe.mari-el.ru does not resolve to address 77.40.62.190: Name or service not known
The mail server hangs up.
The IP just gained "3 week place" in the firewall - in my case iptables, as my server is Debian based. There is not another (pfSense) firewall in front of this server. Further attempts from 77.40.62.190 are black holed.typically, on a @home setup, no one can come in. Never. Period. Maybe somewhat strict, but soooooooooooo easy to administer.
Except a list with known IPs.
Or, if the IP can't be known up front, GEOIP blocking can be considered, but this is far from perfect.
Or, if not, use a VPN, which is build for this scenario. -
Synopsis: Unclear as to why an IDS/IPS blocking (for reason 'X') an attempt to an unused proto/port combination is acceptable, but PF doing it for simply attempting would not be? They both arrive at the same destination, just very different in terms of resources to arrive at the same conclusion. You're likely already consuming an interesting measure of resources between pass/block lists, GeoIP blocks (limited value), IDS/IPS block injection and so on. How would that be any different whether its v4 or v6 - you're still going employ those equivalent protections, right? In one of those tracks you're paying a premium for processing by the IDS/IPS, then the proxy, then ... and finally the service/application to process vs. "source exhibited potentially problematic behavior, prescribe cooling off interval before allowing any more connection attempts" via the least expensive, lowest latency means possible. Like most things, careful consideration is necessary. It's simply another tool in the kit. Exposing the ability to use 'overload' and 'flush global' on rules for both TCP and UDP enables an administrator to address by crafting rule(s) accordingly.
--
Outermost is a transparent bridge running Snort (blocking IP-based categories + categorical rules that pertain to scanning). There's also a laundry list of IPs and networks for pass/block. The outer takes care of 99% of useless/bad traffic.
The next layer is a pfSense firewall (w/NAT) running Suricata + pfBlocker and various other packages. Suricata on the external interface blocks all IP-based categories + numerous additional categories (each interface has its own Suricata instance with rulesets applicable to each interface's purpose). Yes, such things as a haproxy are used to increase security posture and nothing is 'exposed' directly. Patching and updates are done daily to weekly. (followed by successive internal layers)
The aspect of the attempts didn't look like anything interesting until looking back and seeing that they originated across different netblocks/SPs and different locations (appear to be cellular/consumer residential). It wasn't a singular source. Given a small number of packets, some spread out, some in succession and non-repeating IP Addresses made it far less visible. The common aspect was target proto/port (proto in this case was UDP). This could have been easily overlooked as just noise and possibly could be just that - noise. Having Suricata bark the same message when it occurs - isn't stating anything new (but does validate that its doing its job). If something changes about the packet construct (same targeting, different payload), is it a gamble as to whether Suricata would catch it? Sure, it would still be blocked by the firewall (unused proto/port), but in essence something is still 'attempting'. This is where an alternative means (as was described) has merit.
The primary difference in the suggestion is that an IDS/IPS (in its most valuable context) is inspecting payload to determine if something should be blocked - potentially even for an unused proto/port. Arguably, a finely tuned IDS/IPS won't consider those packets but its those packets that also signal to the IDS/IPS that this source should be blocked if its behavior(s) aren't those that conform to expectation. We're just short-circuiting the overhead by using the lowest resource/latency means to address (PF).
Proactively blocking based on blacklist only addresses already known bad actors - it doesn't address sources that aren't on the blacklist or are too spurious/minimal to qualify for blacklisting.
Yes, relying on the eventual destination service (and the steps to go there) and associated strengths (or weaknesses) is certainly viable and part-and-parcel. Preventing the ability to reach the service (in the first place) by sources that exhibit less than desirable behavior when the service must be 'otherwise publicly accessible' (non-veiled, eg: not behind a VPN) - is pragmatic. You are in essence doing same with an IDS/IPS...
As far as v4 vs. v6 - you're likely already utilizing means that pass/block addresses (ad nauseum) as a result of external traffic being rife with scanning, probing and a litany of qualifiers for 'drop/block/discard'. There's substantial overhead to have an IDS/IPS or to have the service, address this (even if to reject) than for PF to prescribe blocking based on recently behavioral pattern of attempt(s) to ports that should never be attempted (externally). Given your 1K+ example, if there was an attempt to a [trigger] port it would have resulted in the source being blocked with comparatively no processing overhead and a lot less logging to traverse (if one is logging, as only the initial catch needs to be logged and not the successive denials). Obviously, if the source never attempted an unused [trigger] proto/port - then it won't help. But what did that cost in terms of resources to have a set of unused [trigger] proto/port combinations defined? If compute resources are a consideration, then this could certainly up the ante. For busier firewalls, this provides an opportunity to potentially log even more strategically. If nothing else, the block interval for the IDS/IPS could be reduced due to the fact that attempts to an unused [trigger] proto/port could have a much longer block interval. From a service delivery perspective, the potential for "lockout" can [conceivably] be shortened when the block is prescribed via the IDS/IPS while using these two methods in tandem (as one would be able to prescribe a longer blocking interval for those connections captured via PF).
As a random example, if one only uses OpenVPN for all VPNs and uses an unusual port (hopefully) - why would UDP/500 ever be targeted for connection by an "expected" consumer? It shouldn't. Block all connection attempts to/from address for <interval> and move on. Don't waste resources to even consider what was in the payload, nor allow it to attempt connection to anything else. Much like the incessant connection attempts to TCP/1433, if it attempts (its not something that you want connecting to anything), just block the source for interval from being able to connect to anything and move on. Why even waste the IDS/IPS's time on traffic that originates from sources that have exhibited such behavior?
Seems unclear as to why there's acceptance to an IDS/IPS blocking a source attempting connection to an unused proto/port combination for 'payload matching on X' and resistance to being able to craft a rule where PF simply blocks that same source for attempting connection to that same unused proto/port combination. Both result in the same logical overhead - one of those just requires far more resources and adds latency to get there.