Taming the beasts… aka suricata blueprint
-
Great article. One comment about the unprivileged ports.
1024 to 65535 unprivileged ports, you don't have any control over these, make a note to remember what ports are privileged
Name the alias something that is easy to remember, like I don't know, how about "outgoing_ports"?Since pfSense is a state-full firewall, should it not be able to sense the switch of communication to the high ports, and open them up automatically? Thus we do not need to open all of them explicitly, but only the ones that correspond to remote services that your network needs to establish new connections with.
Another thing I would add, for those with multiple LAN interfaces, the ‘allow outside’ rule, destination should be set to Not (!) and the alias with a list of all other LAN interfaces. This is to prevent different LAN subnets from talking to each other. I assume you do not want them talking to each other, otherwise what is the point of setting up multiple LAN subnets anyway. This way you do not have to add the floating BLOCK rule; as you said earlier, we should whitelist not blacklist.
Excellent, comprehensive FAQ, I enjoyed reading it, thank you.
-
An allow all rule on the CARP interface isn't technically safe, either. :-)
Especially if you disallow general access to the GUI from non-management workstations, which is a good idea but not always followed… It's more important on guest networks. As long as they're taking the time to lock down their network, they may as well keep the GUI safe, too.pass pfsync from SYNC subnet to any
pass TCP from SYNC subnet to SYNC subnet on pfsense_portsOtherwise your users on LAN can reach the WebGUI on the secondary by using its IP address on the sync interface (it will route, after all). pfsync traffic won't route since it's (directed) multicast so that's safe, but not any other services on the firewall.
Another couple tricks:
Users on LAN can reach the firewall GUI by using the WAN address or SYNC IP address from the LAN, or any other internal interface. This isn't so easy to block on 2.1.x, but on 2.2 you can use the "This Firewall (self)" macro to block traffic going to any IP address on the firewall. -
@G.D.:
Since pfSense is a state-full firewall, should it not be able to sense the switch of communication to the high ports, and open them up automatically? Thus we do not need to open all of them explicitly, but only the ones that correspond to remote services that your network needs to establish new connections with.
No. It doesn't matter if the firewall is stateful or not, pfsense's default is to block everything, even high ports. If you drop the high ports from the outgoing_ports alias, It's very likely you'll break a lot of stuff (messengers/voip/etc). An allow any any rule is exactly that, allow everything going out. My way limits the outgoing traffic somewhat. Yes you could certainly allow only ranges to ports that are actually used.
@G.D.:
Another thing I would add, for those with multiple LAN interfaces, the ‘allow outside’ rule, destination should be set to Not (!) and the alias with a list of all other LAN interfaces. This is to prevent different LAN subnets from talking to each other. I assume you do not want them talking to each other, otherwise what is the point of setting up multiple LAN subnets anyway. This way you do not have to add the floating BLOCK rule; as you said earlier, we should whitelist not blacklist.
A host on the DMZ initiates a connection to the LAN. DMZ is in the 192.168.43.xxx range. Lan is in the 192.168.23.xxx range. Different subnets, as explained earlier. I'll try to explain the process as simple as possible. The DMZ shouts "hey, who has host 192.168.23.46?". pfsense wakes up from its sleep, and says "hey, here, give me that packet, I know how to get to 192.168.23.46". pfsense takes the packet and does what a router does, it routes it to the LAN subnet.
Having different subnets is not a guarantee that they will not talk to each other. Having a firewall with correctly set up rules is (almost :p). If the rules say "if a packet comes on DMZ (or opt2,opt3, ie a floating rule), and wants to be delivered to LAN, if the address is any, just throw it out the window". Having a NOT floating rule allows you to add even the destination interface (yes, even LAN) in the selection. Since the rule says "if the address DOESN'T match LAN…" The rule will be "invalid" on the LAN interface and have no effect. There is a catch though. Put yourself in pfsense's place. A packet comes in on DMZ with an address 192.168.23.185. What does the rule say? If the address is NOT LAN. The source address is on the LAN though, therefore this packet does not match the rule. The packet passes through, and depending on the rest of the rules, it could actually get routed between the subnets :DAn allow all rule on the CARP interface isn't technically safe, either. :-)
Especially if you disallow general access to the GUI from non-management workstations, which is a good idea but not always followed… It's more important on guest networks. As long as they're taking the time to lock down their network, they may as well keep the GUI safe, too.pass pfsync from SYNC subnet to any
pass TCP from SYNC subnet to SYNC subnet on pfsense_portsWell said. A small correction though. allow sync subnet > sync subnet. That in combination with the floating rule I suggested should completely take care of pfsense's ports.
Otherwise your users on LAN can reach the WebGUI on the secondary by using its IP address on the sync interface (it will route, after all). pfsync traffic won't route since it's (directed) multicast so that's safe, but not any other services on the firewall.
Another couple tricks:
Users on LAN can reach the firewall GUI by using the WAN address or SYNC IP address from the LAN, or any other internal interface. This isn't so easy to block on 2.1.x, but on 2.2 you can use the "This Firewall (self)" macro to block traffic going to any IP address on the firewall.Actually that scenario shouldn't apply if everyone uses common logic. Every interface (unless specifically needed) should only have access to pass traffic between that interface and the wan side.
A floating rule to handle this is a blocking quick rule, with all of the interfaces selected (except sync) and the source set as any, destination sync subnet. Every traffic destined for sync should now be dropped on all interfaces. On that note, setting up carp with the secondary IP on the sync subnet, isolates every sync action (states/config changes) from other interfaces, since the 2 hosts are directly communicating on a dedicated line. This is my preferred way to set up carp. The admin interface is the admin interface, with access to mostly everything (since I need to administer servers on other interfaces), accesses the webgui, and the carp members talk to each other over their dedicated line, with no other traffic reaching that line. Technically the SYNC interface should be completely safe this way (except physical access). I'm not arguing that tightening SYNC rules is wrong, and I would actually recommend it as well. The point being though, if an attacker has access to unplug the network cable between the 2 hosts, connect it to a switch, then connect the switch to a malicious host in order to launch an attack on the 2 SYNC hosts, the fortress has already fallen and is burning to the ground :)Edit:
Walked away then came back with an idea. If the documentation specifically says use an IP for the secondary CARP member that is on the SYNC subnet, on the master, then by default traffic is limited to that interface. How about adding a default floating rule for this to new installations, as set up out the box? (yes I do understand that it >might< break some set ups, but progress is progress :) ). That will save new(ish) users from making the mistake of allowing foreign traffic on SYNC. Maybe make it a tick to enable option so that everybody is happy?The same can be applied to the Webgui+SSH. A default floating rule on all interfaces except the admin interface, would also save a lot of people from misconfigurations. Again tick to enable?
-
Good Read. :)
Was hoping to find a detailed explanation and setup about Suricata itself, so waiting for I'm assuming part 3 in this guide.A default rule to isolate as you will the SYNC interface might actually not be a bad idea. I would be amazed if even 10% of all HA setups would be doing this atm.
Maybe I should read this again when i'm not running a fever..
-
Between writing the next part (IP lists), checking the lists, making sure everything works, refreshing my rule configs (what good are howtos if you don't follow them, right?), I can't help thinking why the SYNC interface is not kept completely isolated (even removed from the rules page) and default rules not set.
-
Hi
Thanks, thought no smart human being would put information in this matter. Miss some pictures? I know some stuff have pictures somewhere (maybe references) but all together is always good. Some 20 min. Youtube video? asking to match.
Great stuff. One more time, thanks.
-
If you drop the high ports from the outgoing_ports alias, It's very likely you'll break a lot of stuff (messengers/voip/etc).
Blocking rouge communicators is why a lot of people start looking into filtering outbound traffic by destination port in the first place. So, I would say, in this case ‘breaking a lot of stuff’ is a good thing.
Having different subnets is not a guarantee that they will not talk to each other.
If you delete all firewall rules, there will be no crosstalk between pfSense routed subnets.
Instead of first allowing the traffic, and then blocking it, you could tweak your allow outside rules so that traffic from each of the subnets is allowed to go anywhere except other local subnets.
-
@G.D.:
Blocking rouge communicators is why a lot of people start looking into filtering outbound traffic by destination port in the first place. So, I would say, in this case ‘breaking a lot of stuff’ is a good thing.
The rules I recommended use the outgoing_ports as a destination, not as a source. In that case, filtering the high (unprivileged) ports >will< break a lot of useful stuff. I'm not arguing that sometimes breaking them is not useful, but breaking let's say (simple example, don't know the actual port off the top of my head) skype for the general public isn't as useful. Giving a general recommendation is better, then people can tweak that to fit their actual use case. That's why the snort blueprint and now this topic exist. Because rule maintainers made the assumption that identifying everything on the network is useful. It's actually not useful at all.
Let's examine snort's example. A rule exists to identify a simple HTTP request. While useful (in theory) to identify HTTP requests, the majority (all in use?) of OSs out there will eventually need to issue such a request in order to perform OS/program updates. Following that, a host that will never issue an HTTP request has no place on the public Internet, since it will never update. Using a 40 year old OS is just asking for it.
The same principle can be applied here. I could instead say delete all rules and you are absolutely safe. In theory it is useful. But in practice I'm trying to provide a secure starting point without having to spend the rest of my life supporting it. Minimal breakages then tweaks is more acceptable than total breakage.
@G.D.:If you delete all firewall rules, there will be no crosstalk between pfSense routed subnets.
Instead of first allowing the traffic, and then blocking it, you could tweak your allow outside rules so that traffic from each of the subnets is allowed to go anywhere except other local subnets.
That's what the general floating rules suggested do. They block traffic from interface X destined for Y,Z. The interface's rules should allow for traffic destined for WAN. The good thing about floating rules is instead of creating new rules in the future when you add an interface, you edit the rule and CTRL+click the new interface and done. Also see previous paragraph of why breaking everything isn't as good as it sounds.
-
To show how this guide can be tweaked I'll provide an example for an individual interface. This interface provides internet access to WIFI clients. Ideally, all internal facing interfaces should be close to this.
In order, as shown on the interface's rule page:
rule 1:
| Action | PASS |
| Disabled | NOT TICKED! |
| Interface | The interface you are setting up the rule for |
| TCP/IP Version | IPv4+IPv6. Saves us the trouble of modifying it in the future |
| Protocol | TCP/UDP |
| Source | not NOT TICKED, type Interface's net. Nothing else here |
| Destination | not NOT TICKED, type Interface's net. Nothing else here |
| Destination port range | from DNS to DNS |
| Log | NOT TICKED |
| Description | DNS |rule 2:
| Action | PASS |
| Disabled | NOT TICKED! |
| Interface | The interface you are setting up the rule for |
| TCP/IP Version | IPv4+IPv6. Saves us the trouble of modifying it in the future |
| Protocol | UDP |
| Source | not NOT TICKED, type Interface's net. Nothing else here |
| Destination | not NOT TICKED, type Interface's net. Nothing else here |
| Destination port range | from NTP to NTP |
| Log | NOT TICKED |
| Description | NTP |rule 3:
| Action | PASS |
| Disabled | NOT TICKED! |
| Interface | The interface you are setting up the rule for |
| TCP/IP Version | IPv4+IPv6. Saves us the trouble of modifying it in the future |
| Protocol | TCP see note |
| Source | not NOT TICKED, type Interface's net. Nothing else here |
| Destination | not NOT TICKED, type any. Nothing else here |
| Destination port range | from (other), select outgoing_ports to (other), select outgoing_ports |
| Log | NOT TICKED |
| Description | Outgoing ports |NOTE: We have already broken multiple things here. Remember, our rule only applies to TCP connections. VOIP for example generally uses UDP. If you don't care about that, leave the rule as is. If you broke something you want, then set up the following optional rule:
OPTIONAL RULE SEE NOTE ABOVE. Do NOT set up this rule unless you read the note above 3 times and once more to make sure you understood it completely.
| Action | Pass |
| Disabled | NOT TICKED! |
| Interface | The interface you are setting up the rule for |
| TCP/IP Version | IPv4+IPv6. Saves us the trouble of modifying it in the future |
| Protocol | UDP see note |
| Source | not NOT TICKED, type Interface's net. Nothing else here |
| Destination | not NOT TICKED, type any. Nothing else here |
| Destination port range | from 1024to 65535 |
| Log | NOT TICKED |
| Description | Outgoing ports UDP |Reasoning for the rule: Most UDP traffic passes through high ports. There are exceptions of course, like NTP and DNS. Add rules according to your use case.
At this point, your interface is set up. The problem is that "noise" traffic will get logged as blocked, since you should generally enable default rule logging (harmless traffic, broadcast traffic, etc.). To clean up our logs:
Rule 4 (assuming you did not set up the optional rule above):
| Action | Block |
| Disabled | NOT TICKED! |
| Interface | The interface you are setting up the rule for |
| TCP/IP Version | IPv4 |
| Protocol | any |
| Source | not NOT TICKED, type any. We select any here since broadcast will not match our interface's subnet. |
| Destination | not NOT TICKED, type any. |
| Log | NOT TICKED |
| Description | Tidy logs |Rule 5 (assuming you did not set up the optional rule above):
| Action | Block |
| Disabled | NOT TICKED! |
| Interface | The interface you are setting up the rule for |
| TCP/IP Version | IPv6 |
| Protocol | any |
| Source | not NOT TICKED, type any. We select any here since broadcast will not match our interface's subnet. |
| Destination | not NOT TICKED, type any. |
| Log | NOT TICKED |
| Description | Tidy logs |Those 5 rules (assuming you did not set up the optional rule) are the only rules that exist on this interface. Again, for MY use case.
This guide (as mentioned) is not a spoon feed me guide. Everything I suggested should be created as suggested. Of course I can't cover each and every single use case out there. That's where you tweak the suggested configuration to suit your needs.
-
IP lists
Now that you have completed the first part, it's time to put the knowledge you have gained to good use. We'll be setting up IP lists to help us relieve suricata from the burden of analyzing unneeded packets, by reducing the number of active rules.There are two critical missing features from pfsense though, which would greatly help us in maintaining our lists. The first is that the URL (and URL table) aliases are missing the part where you tell them when to download updated lists. As it stands now, the auto update will check occasionally (update frequency dropdown) but not as often as we would like, with out a way to specify different times for different lists and if there was no update will not check for another week (please correct me if I'm wrong). The second one is that having duplicate entries (multiple lists containing an IP) doesn't get handled, so we end up using more RAM than we would like, and passing a packet through multiple inspections before deciding what to do with it. A feature request for the pfsense team is to add a way to say list 1 should be updated at 1:20am, every day, list 2 should be updated once per hour, list 3 should be updated once per week on Sunday 11:30pm, and so on. In other words, add a way to be able to setup scheduling for the alias updates. Bonus points if de-duplication is handled as well, with a way to say de-duplicate the lists on, say for example, Monday at 3:00am.
A forum member, BBcan177, was kind enough to create a script containing the necessary functions missing. The script was designed to keep snort IP reputation lists up to date, but we'll adapt it to our needs.
We'll use aliases to keep a large number of IPs in a rule. This allows us to set up quick floating rules for a number of interfaces, keeping our per interface ruleset to a minimum. Remember, incoming should always be blocked, outgoing should always be rejected. In the future, when you add an interface, instead of copying existing rules to that interface, you just edit the existing quick floating rules and CTRL+click the new interface and you are done :).
If BBcan177 passes by this thread, please provide the script for public downloading. I do understand that the script is released under GPL, but I'm not willing to take credit for the script by providing the download.
Ok, after acquiring the script, rename "pfiprep v2.2.8 pfiprep.txt" to a simpler name (I don't like spaces or versioning, since it will interfere with our cron job later on let's say badips.sh for example). Rename pfiprep v2.2.8 pfiprepman.txt" to "badipsman.sh".No longer needed, script is renamed to a simpler name on github. Then we'll change a couple of things that need to be changed in order for pfsense to do our bidding.System>Advanced>Firewall/NAT.
Change:
| Firewall Maximum States | 1000000 (1,000,000) |
| Firewall Maximum Tables | 10000000 (10,000,000) |
| Firewall Maximum Table Entries | 10000000 (10,000,000) |Why so high limits? States is what pfsense will keep track of. Unless running mini-pfsenses (<512MB) then you are safe to increase this limit. Tables is self explanatory, saves us the trouble to increase it when we create 1mil aliases :P. Table Entries is what actually needs to be increased. The lists can contain a huge number of IPs. We'll not be running anywhere close to 10mil per list, but it doesn't hurt to give us a little leg room.
TIP WHEN USING CARP
Make the following changes on the CARP slave first, until you reach and follow the BLUE textDownload the scripts (Diagnostics>Command Prompt) and upload them on the CARP master. More on this later.
With the limits lifted, it's time to get the script onto pfsense. Head over to Diagnostics>Command Prompt.
- Use the upload part to well… upload both parts of the script. After hitting upload, look to the top to see where the file ended up. It should show something like "Uploaded file to /tmp/badips.sh".
- Command prompt "mkdir /home/badips" then "ls -la /home/badips" to check that owner is root and group wheel.
- Use the command part to "mv /tmp/pfiprep* /home/badips/".
- "chmod +x /home/badips/pfiprep*" to make them executable.
- "ls -la /home/badips/" and make sure the owner is root and group wheel.
- "mkdir /usr/local/www/badips" this is the folder that will hold our de-duplicated copies of the lists, in order for us to import it into the aliases, and various bits and pieces needed by the script. "ls -la /usr/local/www/badips" and make sure its drwxr-xr-x, owner root, group wheel. The permissions need to be correct so that we can read the list file from other hosts (keep a single SPAMers list on pfsense, and pull it from multiple email servers for example) and the script can write to it. They don't need authenticated access to pull the lists, since it's a simple file on pfsense's webserver. Yes you do need to allow access to the webserver (webgui) first. Depending on your use case it's either acceptable or not. I don't pull the files from other hosts. The files need to be in a web accessible place anyway so that the URL alias can pull in the lists.
- "mkdir /usr/local/www/aliastables" for the script's tier functionality
7) You need to convert the script from DOS endlines to UNIX ones using the tr command. Enter the next commands as shown, replacing the name with your custom one:
No longer needed since moving the script to github. Use the Download gist link on github to get a tar archive with the two scripts
Remember to use the following when editing the script:
userfolder=/home/badips (NO TRAILING /) pfdir=/usr/local/www/badips/ (don't mix them up!)
Diagnostics>Edit File>/usr/local/badips.sh (or whatever you called it) and make the two absolutely needed changes above. While editing the script, read through the comments and make any necessary changes (other than userfolder and pfdir). FIRST TIME RUNING IT CHANGE "bypass=no" TO "bypass=yes", otherwise the script will fail to run. Now is the time to select your favourite lists.
NOTE: Some IP lists are almost guaranteed to include False Positives. Choose the minimum required and adjust accordingly. See comments in script when removing a list. Eventually I'll provide a complete list of all the lists (no pun intended) that I personally use, with the least amount of false positives). I prefer to keep the stuff about the guide that stays relatively unchanged (don't forger the forum's black hole problem) at the start, then add the things that do change over time. Look later in the thread for the recommended lists.
ssh into your pfsense, change to /home/badips.
try to run the script with ./pfiprep.If you are not using CARP, skip below the BLUE text. If you are using CARP, MAKE SURE YOU FOLLOW THE BLUE TEXT.
NOW MAKE THE SAME CHANGES ON MASTER!!! Use Diagnostics>Command prompt to download the scripts from the slave and upload them on the master. This way the desired lists will get replicated on master.
AFTER completing the changes on the master as well, you need to edit both master's and slave's script and change "bypass=yes" to "bypass=no". FROM NOW ON, ONLY DO THE CHANGES ON MASTER, SINCE REPLICATION WILL TAKE CARE OF REPLICATING OUR ALIASES AND FLOATING RULES ON THE SLAVE AS WELL. You can thank me later.Edit the script and change "bypass=yes" to "bypass=no" after initial run
If you don't have the cron package installed, install it now.
Services>Cron.
Add a new cron entry as shown below:| minute | 40 (since no other cronjobs are set up near that timeframe) |
| hour | * |
| mday | * |
| month | * |
| wday | * |
| who | root |
| command | /usr/bin/nice -n20 /home/badips/pfiprep >> /home/badips/download.log 2>&1 |NOTE: When I first installed the script it simply refused to download the lists. I left it overnight, and it downloaded the lists then did it's dedup job correctly. I recommend walking away leaving it enabled, then continue the next day with the following.
Removed because as pointed out by another member, I'm an idiot ;DDiagnostics>Command prompt>Command
"ls /usr/local/www/badips/"
This will give us a list of the files that we need to point our URL table aliases to. It will be different for you (if you enabled different IP lists). I will only provide an example for a single random list (it might, or it might NOT be recommended for use in the end), it's just an example to show how to use the aliases.We'll pick "dShield.txt". Head over to Firewall>Aliases>URLs>click "+" button
I'll give an example for a single alias, then you need to create as many aliases as you have lists enabled.| Name | dshield |
| Description | Simple description to help you identify what the alias is for |
| Type | URL Table |
| URL | https://127.0.0.1:X/badips/dShield.txt | |
| Update Freq. (days) | 1. This is the lowest you can go with pfsenses defaults.see note |NOTE:Let's say X=43. For URL the https://127.0.0.1:43/badips/ part will be same for all other aliases, since it's the directory where our finished lists are located. the dShield.txt part is what file you want to use, and can be found by using the "ls /usr/local/www/badips/" command we used previously.
NOTE: Update frequency should be the lowest possible value (1). This means the lists will be checked once per day by pfsense. The script will take care of maintaining the lists (checking for updates,downloading,deduping) externally, since there are lists that will ban your IP if you check for updates too often. pfsense will just check the local file, and if an update is made, it will refresh its aliases. This is where URL Tables individual scheduling could help if it was implemented directly into pfsense, since we could bypass the script and directly check/refresh everything in pfsense and some lists can be updated 4 times a day, while others once a week. Hope the pfsense developers add this feature.Keep adding other aliases as needed. When done, Firewall>Rules>Floating.
Add a new rule to the BOTTOM of other existing rules.
The rule should be:| Action | Block |
| Disabled | NOT TICKED! |
| Quick | NOT TICKED!!! |
| Interface | WAN and WAN ONLY! If running multiple WANs then select all WAN connections. NOT internal ones. |
| Direction | any |
| TCP/IP Version | IPv4, since currently the lists are for IPv4 addresses |
| Protocol | any |
| Source | not NOT TICKED, type "Single host or alias". start typing ds… and dshield should pop up. Select it. Make sure the red box says dshield |
| Destination | not NOT TICKED, type any. |
| Log | NOT TICKED |
| Description | Inbound dshield |Save and apply. Mouse over dshield (in the Destination column), and a pop up will show up showing some IPs in it. If the popup is empty, it means that the alias is not correct. If it shows 1.1.1.1 it means the list was empty to begin with (handled by the script).
Next up, our internal rule using this alias:
| Action | Reject |
| Disabled | NOT TICKED! |
| Quick | NOT TICKED!!! |
| Interface | ALL internal facing interfaces EXCEPTSYNC. If you select SYNC, you risk breaking syncs since a list could contain private addresses.NO WANs!!! |
| Direction | any |
| TCP/IP Version | IPv4, since currently the lists are for IPv4 addresses |
| Protocol | any |
| Source | not NOT TICKED, type any. |
| Destination | not NOT TICKED, type "Single host or alias". start typing ds… and dshield should pop up. Select it. Make sure the red box says dshield |
| Log | NOT TICKED |
| Description | Outbound dshield |Save and apply.
Keep adding the floating rules after adding your desired URL table aliases. Remember, there are two rules to each alias. One is WAN facing, blocking and one is internal (LAN,DMZ,opt1,opt2,except SYNC!), rejecting.
You have now set up the IP lists to download automatically (the script also has other functions), set up a way for pfsense to become aware of them, and added the necessary rules.
Keep checking this topic for a list of the recommended lists to use. I'll add this eventually.
So far we have limited traffic using pfsense. How far are we in our suricata goal though?
An example is the emerging-tftp.rules category. This category contains rules that are explicit to port 69, and guess what? We already handled this in pfsense, so no need to enable that category.
Another example is the emerging-compromised.rules rules. Since this category detects traffic to IPs listed in Emerging Threat's Compromised list, and we'll use this list, I'll let you figure out if it needs to be enabled ;)That completes (almost, the recommended lists are missing) part 2 of this guide. Next up… suricata!
As always, feel free to call me an idiot (as above), flame me, or add your comments and corrections :D
Keep checking this threat, the interesting stuff has just begun...
-
Recommended lists.
This MAY or MAY NOT get changed in the future. Please go through the thread in the future to see if an updated version is available. I'll try to keep the updates to posts, for as much as I can, after that, I'm afraid to cause the forum's black hole.
The left column is my alias name, and the right column is the file (/usr/local/www/badips/$file), See post above how to add this to the aliasesabuse_palevo AbusePalevo.txt
abuse_spyeye AbuseSpyeye.txt
abuse_zeus AbuseZeus.txt
alienvault ALIENVAULT.txt
atlas_attacks Atlas_Attacks.txt
atlas_botnets Atlas_Botnets.txt
atlas_fastflux Atlas_Fastflux.txt
atlas_phishing Atlas_Phishing.txt
atlas_scans Atlas_Scans.txt
atlas_ssh Atlas_SSH.txt
ciarmy CIArmy.txt
danger_rules DangerRulez.txt
drg_http DRG_http.txt
drg_ssh DRG_SSH.txt
drg_vnc DRG_VNC.txt
dshield dShield.txt
et_comp ET_Comp.txt
feodo_bad Feodo_Bad.txt
feodo_block Feodo_Block.txt
geopsy Geopsy.txt
iblock_badpeer IBlock_Badpeer.txt
iblock_bt_fs IBlock_BT_FS.txt
iblock_bt_hijack IBlock_BT_Hijack.txt
iblock_bt_spy IBlock_BT_Spy.txt
iblock_bt_web IBlock_BT_Web.txt
iblock_onion IBlock_Onion.txt
infiltrated Infiltrated.txt
malc0de malc0de.txt
malware_group MalwareGroup.txt
mdl MDL.txt
nothink_bl NOThink_BL.txt
nothink_malware NOThink_Malware.txt
nothink_ssh NOThink_SSH.txt
openbl OpenBL.txt
p24_spamcop p24Spamcop24.txt
shunlist Shunlist.txt
spamhaus_drop Spamhaus_drop.txt
spamhaus_edrop Spamhaus_edrop.txt
sri_attackers SRI_Attackers.txt
sri_cc SRI_CC.txt
tor TOR.txt
virbl VirBL.txt
vmx VMX.txt
watchguard WatchGuard.txtA bit of searching around in the script should be enough to match my list to the lists enabled in the script. I could provide a script snippet showing the enabled lists, but meh :P
This particular list of lists (again, no pun intended) is in use on a production network, providing connectivity to servers and clients. I can't remember the last time I had to fiddle around with the lists due to a false positive. I do remember the last time was removing alienvault from the lists. Been running like this for a few months now (on an old customize version of the script, and that's why I had to edit the above post multiple times, migrated to a newer version).It's a total of 44 lists. Double that (each list needs 2 floating rules) and you only have to set 88 floating rules.
A reason why I don't use the script's tier functionality (combining multiple lists to a single alias) is because since this is a production network I might have to identify false positives and make changes fast to it. Haven't had to change the floating rules for a while though :D.Now, class, finish your homework by the next time. And make sure you brush up on the previous parts when that time comes . Hint: writing custom suricata rules for use on a network gateway. Yes diving straight to the deep waters. You've already got so far in your training, yet still fail to understand the reason for all this work…tsk..tsk...young grasshoppers...
You are already ahead of the curve, just the information provided in these two parts could land you a 5K/month job as a network administrator for a Fortune 500 company. Trust me, you know stuff the competition doesn't even imagine exists. Next up, we'll take your training to the next level and offer you the chance to become one of the best network administrators/security experts in the world by awakening the beast... -
Suricata
Everyone should have completed the two previous parts of the guide before moving on to this part. This sets everything up so that when the beast is truelly awaken, it will work in your favor, instead of against you. Some instructions in this part (and explanations) apply equally to suricata and snort. I'll mention only suricata, since this IS the suricata topic after all.
I know most of you are anxious and want to dive right in. First things first. We need a "wax on, wax off" session first.
Who will be our attackers
Bet you didn't see that coming. Our attackers are persons/corporations/state-funded-actors that are not previously identified. Since we are using IP lists to block traffic from known sources, if the attacker's packets pass through pfsense (reaching the wan side is ok, since known are dropped) then the attacker has not attacked a critical sensor system (one that adds to the lists). Keeping with snort's topic's NSA theme "the SIGINT simply isn't there".Since we have already identified the "usual suspects", we are dealing with, let's say 20% of the total bad traffic (assuming 80% is known).
How will you know that packets are arriving from an unknown bad IP?
- Those packets will reach a legitimate port and pass across pfsense to a server/process listening behind pfsense. In this case they will be analyzed in transit (or intercepted if running in IPS mode) by our fire breathing dragon (suricata).
- Those packets will NOT reach a legitimate (open) port and will be dropped by pfsense's default block rule. We could monitor the default rule and set up bans based on that. We'll do it in a far more interesting way, using suricata.
The way suricata works on pfsense can be thought as being as close to the network as possible. Packets (technically copies of packets so far, since we are not running in IPS mode) are passed through suricata at the same time pfsense gets the actuall packet. So let's say a bad source packet arrives at our firewall. The packet is copied, then the original is forwarded to pfsense at the same time the copy is forwarded for analysis. The original will be dropped by pfsense, but the copy can fire up an alert.
Why is this useful? We can leverage our suricata systems to keep their own IP lists, in the form of banned hosts. Bad packets (bad refers to a closed port destination) will be dropped by pfsense with no indication to the attacker, and at the same time our attacker will be identified and put on our own list. If the attacker decides to perform another port scan, for example, a week later, suricata will still pick up on that and fire up a new alert, refreshing the initial ban day. So instead of being 28-7=21 days from now, with the refreshed alert is will be 28 days from now (pfsense is already dropping the original packets, since that host is now on an internal alias, and the packets will not be logged). You can see that as long as the attacker attacks us, he will be kept on a perpetual ban. The harder they try, the worst it is for them.
NOTE: The rules explained in this part are rules that should be run on each and every single gateway system. They are rules especially designed for such use, since our bastion (first systems that can be reached from the network) must be our bastions, our "impenetrable" outer perimeter. Quotes because as proven by history, even the mightiest of the castles have fallen.
QUIZ: Who remembers why low (privileged ports) are useful?
Using the low ports we can detect port scans looking like legitimate traffic reaching "official" server ports. Let's examine a random example:
The attacker sends traffic for port 514 (syslog), containing a legitimate syslog entry.
We have 2 choices to deal with this traffic. Set up a rule especially for it, or set up a general unused ports rule. Remember, suricata will add a new alert each time a rule is triggered, which means if an attacker scans 80 low ports, there will be 80 alerts logged for it, making the blocked tab page a mess. If the alert matches the previous one though, only the timestamp is updated, which keeps everything running smoothly. Further analysis can be performed through the logs.In other words, packets from a source NOT our home network (or belonging to an external network) and a source port of any, reaching a port NOT in use on our home network, will alert us.
Congratulations young grasshopper, you have just created the world's top snort/suricata rule. It is internally referred to in The Company as "The Golden Standard for writing IDS/IPS rules" or, depending on the day "The two rules to rule them all". Why is it the golden standard? Those of you that failed to see that it is impossible to cause a false positive by this rule so far are dangerously close to failing the class. Unless you ignored a port in use (which shouldn't happen all that often) a packet that triggers this rule is a packet that will not route across pfsense. Simply put: a legitimate alert.
Be extremely careful with the knowledge. It can be used for good, or it can cause great harm. These two (a TCP and a UDP), the "The two rules to rule them all", rules accounts for 10K monthly banned hosts (hosts set up to be unbanned after 28 days, but trigger the rule before that).Let's examine why the rule is so successful. We have already mentioned its ability not to cause false positives. One of its other abilities is that it acts as close to the actual protocol as possible. There is no need to pass a packet through deep packet inspection to see what is actually in it, since it is a packet that would otherwise be dropped. Saves us the processing and provides a further ability: detection of traffic that would otherwise be missed by suricata.
"Wax on, wax off" session: HTTP traffic comes in wanting to initiate a connection to pfsense's HTTP port. We are already running HTTP servers behind pfsense, but they use a different IP for that. A legitimate connection attempt to a non legitimate destination.
So, a packet has arrived that is sourced NOT from our network, having a source port of any, and is destined for a NOT HTTP server, to an HTTP port. Get it? ;)
The next question will separate those that want to use this topic as a way of getting a 10K/month job (5K was when you finished a previous part, you are now in the position to basically walk in to any company you want and tell them to hire you for an arbitrary salary) and those that are truelly interested in network security.
Should a low (<1024) port communicate directly with another low port?
The answer is no. Low ports should always be used as the DESTINATION of the connection, NOT the source.
So, a packet that claims to come from a port which starts at 0 and ends at 1023 shouldn't be reaching a port that starts at 0 and ends at 1023. If most potential employers failed to see why you are one of the best there is in the network security industry, tell them the above rule. They will not be able to find the pen to sign your contract fast enough.You now have the necessary knowledge of setting up custom rules for use in pfsense's suricata use case (a network gateway). This allows you to shift processing from Layers 5-7 of the OSI model (actually opening up the packet and looking inside, which is useless if using encryption), to Layer 4 (TCP is layer 4, you are forgeting the first level, physical (cables)). This offers lower load, since you are spending less time processing the traffic, while at the same time not reducing your security. Simply put, you have just awaken the beast…
Those of you that reached this far and "saw the light" will go on in their lives becoming the top of your classes in the best universities of the world, and upon graduating from said universities, will pursue a career in network security, quite possibly for an alphabet-soup-agency. What ever your future goals are, I have a simple request from you: "Always try to the best at what you do. There is the first place and there is the last place. Second place is not an option."
You have now set up the battle so that the sun is behind you, your shield is on your left, the hill is on your right, and the enemy is straight ahead. Sun Tsu was right, you are now only dealing with determined attackers. Suricata is screaming "bring it on".
That completes the "static" part of this topic. Since old posts cannot be edited, I wanted to put this as close to the top as possible. The IP lists list and the enabled suricata rules will be posted from time to time to this thread, so please check the entire thread for the most up to date version.
FAQs
"Why didn't you just gave away your custom rules?" Because quite frankly I've spent 17 years of my life studying and don't want to see my efforts being used as a way for an idiot to get a high paying job. Those that truelly want to learn about suricata (and snort) rules have already picked up the hints and are on their way to writing their rules already.
"Why did you give away all this?" You having a more secure network is inversely proportional to my time spent sifting through logs, trying to identify infected/malicious/compromised remote hosts :D. That and the fact that setting up IDS/IPS systems my way has been proven to be the best way to set them up.
"Who are you?" As mentioned in the first post, "Security through obscurity".
"Who do you work for?" As mentioned in the first post, "Security through obscurity".Next up, and after much anticipation, suricata enabled rules. :D
-
I have been working on a script that downloads over 50 different Blocklists and performs a duplication check to reduce the size of the data. It can download .CSV, .TXT, ,GZ, .ZIP files and also scrape from certain websites that post only a web copy of their Blocklists.
ie : ET, Spamhaus, IBlock, dShield, Atlas, Alienvault etc.. I have been researching Blocklists for several Months and have found the current list to be beneficial in Blocking Malicious IPs.
It utilizes a tool called "Grepcidr" to make the de-duplication work.
It also looks at the number of IP addresses found in a /24 range and can condense the list and enter a /24 block instead. This is done in three ways
- Using a "max" variable, if it finds over the Max variable it will perform a local Maxmind Geoip Database lookup and will process a /24 block for configured Foreign Countries on an individual Blocklist Basis.
- Using a "dmax" variable if it finds over the dmax variable it will perform a Maxmind Geoip Database lookup and will process a /24 block for configured Foreign Countries at the end of the download process on all of the Blocklists together.
- Using a "pmax" variable, if it finds over the dmax variable it will process a /24 Block excluding Country Code whitelist at the end of the download process on all of the Blocklists together.
So I set max to 5, dmax to 5 and pmax to 50 in my setup.
Depending on how aggressive / conservative an admin wants to configure the processes or disable them completely and just use the de-duplication processes.
I have been testing it for several weeks without the need for pfBlocker to reload the Alias tables. Options also exist to place the Repeat Offender Ranges into a "Match" List that can be used with "Floating Rules" to report when these suspected ranges are in your network.
I also found a way to use the Maxmind database to make a Country Code Specific Blocklist, excluding whitelisted countries.
Here is a snapshot of the IP count for each list (mail server lists not included)
Orginal list of approx 700,000 IPs (worst of the worst!)
===[ [b]Blocklist IP Counts ]===========================
240818 total
127685 /home/user/pf/BadIPs.txt
47095 /home/user/pf/IBlock_Badpeer.txt
23423 /home/user/pf/ALIENVAULT.txt
6406 /home/user/pf/Geopsy.txt
6282 /home/user/pf/SRI_Attackers.txt
5307 /home/user/pf/VMX.txt
4818 /home/user/pf/IBlock_Onion.txt
3692 /home/user/pf/Infiltrated.txt
2904 /home/user/pf/IBlock_BT_Spy.txt
2813 /home/user/pf/HackedReport.txt
1570 /home/user/pf/ET_Block.txt
1423 /home/user/pf/IBlock_BT_Web.txt
1139 /home/user/pf/DRG_http.txt
1057 /home/user/pf/MDL.txt
1037 /home/user/pf/ET_Comp.txt
559 /home/user/pf/SnortBL.txt
446 /home/user/pf/Atlas_SSH.txt
378 /home/user/pf/Greensnow.txt
371 /home/user/pf/CIArmy.txt
358 /home/user/pf/Spamhaus_CC.txt
357 /home/user/pf/IBlock_BT_FS.txt
275 /home/user/pf/MTA.txt
239 /home/user/pf/NOThink_Malware.txt
188 /home/user/pf/Maxmind_Proxy.txt
152 /home/user/pf/DRG_VNC.txt
85 /home/user/pf/dShield_Top.txt
83 /home/user/pf/Blut_TOR.txt
76 /home/user/pf/DRG_SSH.txt
68 /home/user/pf/BotScout.txt
66 /home/user/pf/Juniper_Spam.txt
56 /home/user/pf/Snort64.txt
49 /home/user/pf/HoneyPot.txt
40 /home/user/pf/malc0de.txt
39 /home/user/pf/IBlock_BT_Hijack.txt
39 /home/user/pf/DangerRulez.txt
37 /home/user/pf/NOThink_BL.txt
36 /home/user/pf/MalwareGroup.txt
28 /home/user/pf/Feodo_Block.txt
23 /home/user/pf/Spamhaus_edrop.txt
21 /home/user/pf/OpenBL.txt
17 /home/user/pf/WatchGuard.txt
15 /home/user/pf/dShield_Block.txt
14 /home/user/pf/SRI_CC.txt
10 /home/user/pf/Atlas_Fastflux.txt
8 /home/user/pf/Shunlist.txt
8 /home/user/pf/Atlas_Phishing.txt
7 /home/user/pf/Atlas_Botnets.txt
6 /home/user/pf/NOThink_SSH.txt
4 /home/user/pf/Atlas_Attacks.txt
3 /home/user/pf/Atlas_Scans.txt
1 /home/user/pf/Spamhaus_drop.txt <–-- These below are actually empty with
1 /home/user/pf/ISC_top10.txt a "1.1.1.1" as a placeholder.
1 /home/user/pf/Feodo_Bad.txt
1 /home/user/pf/AbuseZeus.txt
1 /home/user/pf/AbuseSpyeye.txt
1 /home/user/pf/AbusePalevo.txt(Here is the status of the pfSense Alias Tabes (Groups/Tiers) update process)
===> Sanity Checks PASSED, Updating Group Lists <===
Updating [ IR_PRI1 ] [ ET_Comp ET_Block Spamhaus_drop Spamhaus_edrop Spamhaus_CC CIArmy AbuseZeus AbuseSpyeye AbusePalevo dShield_Top dShield_Block SnortBL ISC_top10 Snort64 ]
no changes.Updating [ IR_PRI2 ] [ ALIENVAULT Atlas_Attacks Atlas_Botnets Atlas_Fastflux Atlas_Phishing Atlas_Scans Atlas_SSH SRI_Attackers SRI_CC HoneyPot ]
no changes.Updating [ IR_SEC1 ] [ MDL NOThink_BL NOThink_SSH NOThink_Malware DangerRulez Shunlist Infiltrated DRG_SSH DRG_VNC DRG_http Feodo_Block Feodo_Bad WatchGuard VMX Geopsy MTA Maxmind_Proxy BotScout HackedReport Juniper_Spam Greensnow ]
no changes.Updating [ IR_SEC2 ] [ MalwareGroup OpenBL malc0de ]
no changes.Updating [ IR_SEC3 ] [ BadIPs ]
no changes.Updating [ IR_IB ] [ IBlock_BT_Hijack IBlock_BT_FS IBlock_BT_Web IBlock_BT_Spy IBlock_Badpeer ]
no changes.Updating [ IR_TOR ] [ IBlock_Onion Blut_TOR ]
no changes.pfSense Table Stats
–-----------------
table-entries hard limit 800000
Table Usage Count 512459Thanks to jflsakfja, for helping to test it out. ;) ;)
Here is a link to GitHub(Gist) where you can download the files. This provides more functionality than what is available in the vanilla pfBlocker.
[ [b]https://gist.github.com/BBcan17/67e8c456cb399fbe02ee ]
There are installation instructions in the script. If you need more help send me a PM or a post.
Please be careful when working in the shell.** [ From time-time please review any Revisions in the Gist ]**
-
"also scrape from certain websites that post only a web copy of their Blocklists. "
That last part could become quite handy indeed.
Thanks for sharing your script. -
UPDATE: I have updated my script pf IP Reputation Manager to v2.3.1
https://gist.github.com/BBcan17/67e8c456cb399fbe02ee
If anyone needs any help to install please let me know.
Your Feedback is always welcome.
-
@jflsakfja great write up! I have to agree with you; block everything and open up what is needed… To bad I don't do this on my box at home, well my lan is open but my other interfaces are not. So i'm half way there.
@BBcan177 Thank you so much for sharing. When jflsakfja mention the script the other day, I started to search everywhere (including github) but couldn't find it :-( I've been a big fan of pfBlocker but there are too many dups because of list overlap and it doesn't allow you to import other formats.. Maybe someday your script and pfBlocker can get married and have a honeymoon...
I'm using the script basically out of the box without making any major changes to it (Other then disabling the TOR EXIT lists, enabling 2 list from the MAILSERVER section and BadIPs.
Since pfIPRep creates and updates the following pf Tables:
IR_PRI1
IR_PRI2
IR_PRI3
IR_SEC1
IR_SEC2
IR_SEC3
IR_IB
IR_TOR
IR_MAIL
IR_CC
I use them for my URL Alias name. This way, pfSense doesn't create a new pf TableUrl Aliases:
I've created my floating rules like this:
Example of my Outbound Block rule:
Notice in the the description, I started it with the alias name.. This could be used for label matching within your USER: ruleset if needed.Example of my inbound Reject rule:
-
Thanks Cino, I'm glad that you are using the Script ;)
I suggest that you add "enable logging" on the Floating Rules so you can see what is getting Blocked.
I have also added your recommendations for the Widget. (pfIP_Reputation.widget.php)
The widget can be found in my Github GIST.
Copy and save that file in [ [b]/usr/local/www/widgets/widgets ]
From pfSense Status:Dashboard
Click the "+" Icon and add the new "pf_IP_Reputation" Widget"
You may also notice that there is also a "mastermatch" alias that can also be placed into the Floating Rules as a "MATCH" Rule. These are IP Ranges that are in the Safe Country List, but are repeat offending IP Ranges. This can help to indicate malicious behaviour.
-
Example of my Inbound Block rule:
…
Example of my Outbound Reject rule:FTFY :)
Other than that, everything looks good.
EDIT!!!! MISSED THE QUICK CHECKBOX. TICK THAT!A small update on the suricata rules. I'm delaying their release because I wanted to enable all the rules and work my way towards an FP free install, just like snort. The trouble is that I've had to do all the work I did over a few years, in a few weeks. The good news is that most disabled rules are the same on snort and suricata. The medium news is that I still haven't hit all the FPs :p.
I haven't made up my mind if I'll post on the topic recommendations to disable rules no longer needed, since they are handled by the custom rules mentioned previously. Maybe I'll add a small note to them that they can be disabled if using custom rules.
-
I have posted version 2.3.2 of pf IP Reputation Manager to my Gist.
https://gist.github.com/BBcan17/67e8c456cb399fbe02ee#file-pfiprepman_2-3-2
No recent changes to the pfiprep script. You can replace the pfiprepman script completely with this one.
I have also added some code to the pfSense php script /usr/local/www/diag_dns.php
ScreenShot http://imgur.com/L9GeYa2
This will allow you to click on a Blocked IP in the Firewall Log, and it will show you which Blocklists have the Blocked IP Listed. At the bottom are several Threat Sources that can be referenced as well. When 2.1.4 comes out, I will post a new Patch as there are some other changes being made in this file also.
I have created a "patch" that can be applied to pfSense v 2.1.3 (Haven't tested it on other versions, but should work?)
If you don't have the pfSense Package "System Patches", it is available in the pfSense System:Packages list under "System Patches"
Click the "+" Icon to add a new Patch
Enter a Description (diag_dns.php Patch)
In the Patch Contents Dialog Box - Copy/Paste from my Gist the contents of this
link below:https://gist.github.com/BBcan17/67e8c456cb399fbe02ee#file-diag_dns-php_patch
After you paste the patch, look for this line and change it to your pf folder location.
```
$query_list =grep {$hosttrim} /YOUR/BLOCKLIST/FOLDER/* | sed 's/^.*[a-zA-Z]\///'
;These changes need to be made also: Base Directory - **/usr/local/www/** Click **"Save"** Click **"Test"** Look at the top of the patch that it can be successfully added, then Click **"Apply"**
-
Here is a good example about why Reputation in a /24 network is important to monitor:
A recent DNS amplification attack caught by Snort.
The IP Range is listed by 5 different Blocklists, but none of them have that exact IP Range.
The Country code for 204.124.183.211 is in the US. I currently have my script set to not apply a /24 block to a repeated offender IP Range based in the US.
( See ScreenShot ) http://imgur.com/xkRXSFi