commit 4ad4e4d92bee8d500458ad2f6c2c1cf0eeae2105 Author: buckwheat Date: Wed Feb 25 12:10:07 2026 -0800 homepage: Init repo diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f65236a --- /dev/null +++ b/LICENSE @@ -0,0 +1,5 @@ +Copyright (C) 2026 by Buckwheat + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.org b/README.org new file mode 100644 index 0000000..fac1a49 --- /dev/null +++ b/README.org @@ -0,0 +1,7 @@ +#+title: The Official Buckwheat Homepage +#+author: Buckwheat +#+options: html-postamble:nil html-preamble:nil toc:nil + +That's right, I was not lying when I said my website was generated using org-mode in Emacs. Now you can see all my org files I write to generate my HTML, all licensed user the 0BSD just as I'd like it. + +I won't accept any pull requests on this for obvious reasons, I just like open sourcing my things and maybe the way I write my org files might inspire other people to start using org-mode to generate HTML pages. diff --git a/about_me.html b/about_me.html new file mode 100644 index 0000000..14eabb5 --- /dev/null +++ b/about_me.html @@ -0,0 +1,300 @@ + + + + + + + +About me + + + + + + +
+
+

+Click here to return to the homepage +

+
+ +
+
+

About Me

+
+ +
+

buckwheat.jpg +

+
+
+ +
+
+
+

Who are you?

+
+

+I'm Buckwheat, or sometimes patchmeifucan in Cyber Security circles; and I wear quite a few hats. I'm a System Administrator that primarily deals with FreeBSD, I'm a Network Engineering and Cyber Security student, and I do some Systems Programming in my spare time. I've always had an interest in Offensive Security for my entire life but I also enjoy the Defensive Security work of DFIR and Malware Analysis. +

+ +

+I play around with all OSes but I particularly am a heavy user of the many flavours of BSD. Most of my Cyber Security knowledge is from hands-on tinkering in my spare time. I'm an entirely self-taught programmer, and I have familiarity with C, C++, Go, Lisp, Nim, JavaScript, Python, Racket, and Ruby. I'm also capable of reading x86 Assembly, but terrible at writing it myself. +

+
+ +
+
+
+
+

Software I use in my daily life and in my research

+
+

+I use a lot of different tools for my research of both Offensive Security and Defensive Security as well as my Systems Programming. I also use a lot of different tools in my day-to-day to make my life easier. Below is a curated list of what I especially use for the many tasks I perform in my life. +

+ +
    +
  • FreeBSD1
  • +
  • OpenBSD1
  • +
  • NetBSD1
  • +
  • Arch Linux2
  • +
  • GNU Emacs3
  • +
  • Ghidra4
  • +
  • GNU Debugger
  • +
  • Valgrind
  • +
  • Wireshark
  • +
  • Autoruns5
  • +
  • Process Monitor5
  • +
  • x64dbg5
  • +
+
+
+
+

Contact

+ +
+
+
+
+

Footnotes:

+
+ +
1

+I run these both on the same computer, but I swap between separate SSDs that each are dedicated to an install. I have a 3rd SSD for that same computer for running NetBSD as well. +

+ +
2

+Eventually being switched for NetBSD as well, is primarily kept for some personal things, I don't actually care much for Linux. +

+ +
3

+Also the very thing I make this website with! +

+ +
4

+Considering picking up Radare2 with a Decompiler Plugin as I wish to switch to using OpenBSD on one of my other computers for Malware Analysis and Ghidra's OpenBSD port is currently broken. +

+ +
5

+On Windows specifically when doing behavioural analysis of Windows Malware. +

+
+ +
+ + +
+
+ + diff --git a/about_me.org b/about_me.org new file mode 100644 index 0000000..1d1c507 --- /dev/null +++ b/about_me.org @@ -0,0 +1,54 @@ +#+title: About me +#+date: 2025-11-19 +#+author: Buckwheat + +#+options: html-postamble:nil html-preamble:nil num:nil title:nil toc:nil +#+HTML_HEAD: + +#+HTML:
+[[https://buckwheat.neocities.org/][Click here to return to the homepage]] +#+HTML:
+ +#+HTML:
+* About Me +#+ATTR_HTML: :style border-radius:50%; +[[./assets/buckwheat.jpg]] +#+HTML:
+ +#+HTML:
+** Who are you? +I'm Buckwheat, or sometimes patchmeifucan in Cyber Security circles; and I wear quite a few hats. I'm a System Administrator that primarily deals with FreeBSD, I'm a Network Engineering and Cyber Security student, and I do some Systems Programming in my spare time. I've always had an interest in Offensive Security for my entire life but I also enjoy the Defensive Security work of DFIR and Malware Analysis. + +I play around with all OSes but I particularly am a heavy user of the many flavours of BSD. Most of my Cyber Security knowledge is from hands-on tinkering in my spare time. I'm an entirely self-taught programmer, and I have familiarity with C, C++, Go, Lisp, Nim, JavaScript, Python, Racket, and Ruby. I'm also capable of reading x86 Assembly, but terrible at writing it myself. +#+HTML:
+ +#+HTML:
+** Software I use in my daily life and in my research +I use a lot of different tools for my research of both Offensive Security and Defensive Security as well as my Systems Programming. I also use a lot of different tools in my day-to-day to make my life easier. Below is a curated list of what I especially use for the many tasks I perform in my life. + ++ FreeBSD[fn:1] ++ OpenBSD[fn:1] ++ NetBSD[fn:1] ++ Arch Linux[fn:2] ++ GNU Emacs[fn:3] ++ Ghidra[fn:4] ++ GNU Debugger ++ Valgrind ++ Wireshark ++ Autoruns[fn:5] ++ Process Monitor[fn:5] ++ x64dbg[fn:5] + +[fn:1] I run these both on the same computer, but I swap between separate SSDs that each are dedicated to an install. I have a 3rd SSD for that same computer for running NetBSD as well. +[fn:2] Eventually being switched for NetBSD as well, is primarily kept for some personal things, I don't actually care much for Linux. +[fn:3] Also the very thing I make this website with! +[fn:4] Considering picking up Radare2 with a Decompiler Plugin as I wish to switch to using OpenBSD on one of my other computers for Malware Analysis and Ghidra's OpenBSD port is currently broken. +[fn:5] On Windows specifically when doing behavioural analysis of Windows Malware. +#+HTML:
+ +#+HTML:
+** Contact +Codeberg: [[https://codeberg.org/buckwheat][buckwheat]] +Email: [[mailto:patchmeifucan@waifu.club][patchmeifucan@waifu.club]] +Matrix: [[https://matrix.to/#/@buckwheat:unredacted.org][@buckwheat:unredacted.org]] +#+HTML:
diff --git a/assets/buckwheat.jpg b/assets/buckwheat.jpg new file mode 100644 index 0000000..cb6c53d Binary files /dev/null and b/assets/buckwheat.jpg differ diff --git a/assets/buckwheat_button.png b/assets/buckwheat_button.png new file mode 100644 index 0000000..2595786 Binary files /dev/null and b/assets/buckwheat_button.png differ diff --git a/assets/tokyonight.css b/assets/tokyonight.css new file mode 100644 index 0000000..617cc60 --- /dev/null +++ b/assets/tokyonight.css @@ -0,0 +1,306 @@ +@import url(http://fonts.googleapis.com/css?family=Inconsolata); +@import url(http://fonts.googleapis.com/css?family=PT+Sans); +@import url(http://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700); +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} +audio, +canvas, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden] { + display: none; +} +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +a:focus { + outline: thin dotted; +} +a:active, +a:hover { + outline: 0; +} +h1 { + font-size: 2em; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +mark { + background: #ff0; + color: #000; +} +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} +pre { + white-space: pre-wrap; + word-wrap: break-word; +} +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 0; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +button, +input, +select, +textarea { + font-family: inherit; + font-size: 100%; + margin: 0; +} +button, +input { + line-height: normal; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +input[disabled] { + cursor: default; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +textarea { + overflow: auto; + vertical-align: top; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +html { + font-family: 'PT Sans', sans-serif; +} +pre, +code { + font-family: 'Inconsolata', sans-serif; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: 'PT Sans Narrow', sans-serif; + font-weight: 700; +} +html { + background-color: #001f3f; + color: #bbbbbb; + margin: 1em; +} +body { + background-color: #2d3436; + margin: 0 auto; + max-width: 23cm; + border: 1pt solid #f7d794; + padding: 1em; +} +code { + background-color: #2d3436; + padding: 2px; +} +a { + color: #f7d794; +} +a:visited { + color: #2eec71; +} +a:hover { + color: #2eec71; +} +h1, +h2 { + color: #ff6b6b; +} +h3, +h4, +h5, +h6 { + color: #ff92a1; +} +pre { + background-color: #2d3436; + color: #bbbbbb; + border: 1pt solid #f7d794; + padding: 1em; + box-shadow: 5pt 5pt 8pt #073642; +} +pre code { + background-color: #2d3436; +} +h1 { + font-size: 2.8em; +} +h2 { + font-size: 2.4em; +} +h3 { + font-size: 1.8em; +} +h4 { + font-size: 1.4em; +} +h5 { + font-size: 1.3em; +} +h6 { + font-size: 1.15em; +} +ul { + list-style-position: inside; +} +.tag { + background-color: #073642; + color: #d33682; + padding: 0 0.2em; +} +.todo, +.next, +.done { + color: #002b36; + background-color: #dc322f; + padding: 0 0.2em; +} +.tag { + -webkit-border-radius: 0.35em; + -moz-border-radius: 0.35em; + border-radius: 0.35em; +} +.TODO { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #2aa198; +} +.NEXT { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #268bd2; +} +.ACTIVE { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #268bd2; +} +.DONE { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #859900; +} +.WAITING { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #cb4b16; +} +.HOLD { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #d33682; +} +.NOTE { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #d33682; +} +.CANCELLED { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #859900; +} diff --git a/blog/failed2ban.html b/blog/failed2ban.html new file mode 100644 index 0000000..fe7efe5 --- /dev/null +++ b/blog/failed2ban.html @@ -0,0 +1,387 @@ + + + + + + + +Failed2ban - A Real Test In The Trenches + + + + + + +
+
+

+Click here to return to blog posts menu +

+
+ + + +
+ +
+

failed2ban.png +

+
+
+ +
+
+

Intro

+
+

+Hey! It's been a while since there's been activity, huh? Well, worth first saying (even if almost 2 months late) Happy New Years to all my readers. +

+ +

+I recently became a founding member of a multinational group of FOSS Developers and Advocates called Neo-Sekai Club (more about that in a future post of mine!), and I'm in charge of many, many tasks, System Administration and Network Engineer being two of these tasks. In this blogpost, I go over real boots-on-the-ground experience of trying Fail2ban on production FreeBSD servers used by Neo-Sekai Club to see whether the thing everyone uses is really always the thing that works! +

+
+ +
+
+
+
+

The Battlefield

+
+

+It goes without saying that the moment your server touches the internet, you're going to start having script kiddies and botnets hammering on your SSH, firing off port scans, and all sorts of other things. This totally sucks, and this is why we use firewalls. At Neo-Sekai Club, we deploy all of our servers using only BSDs. In this on-the-ground test, this is from real experience using a FreeBSD 14.3 server that we host our web services from. +

+ +

+We use Packet Filter (pf) as our firewall, which is a fantastically simple firewall ported over from OpenBSD and is just as much of a breeze to use over on FreeBSD. Packets get scrubbed in on our interface, logged out to the pflog, and if that's not a port we've whitelisted in the firewall, we block it. Pretty simple system to use! However, that's just not enough in a real-world scenario when it comes to SSH bruteforce attempts. If this was a Linux server, here's now where we're getting into using a system like Fail2ban. So… what exactly is Fail2ban? +

+
+ +
+
+
+
+

Enter Fail2ban

+
+

+Fail2ban is a Python-based security system that integrates into your firewall and provides an IP blacklist based on a number of failed SSH attempts within an alloted timeframe, and then issues bans on IPs who've failed SSH enough times for a period specified by the System Administrator. In the World of Linux, this is a very common anti-bruteforce system that System Administrators use to stop bruteforce attacks in their tracks, and it integrates quite nicely into Linux's firewall system iptables. Here's the thing however, we're not on Linux, and we don't get to use iptables on FreeBSD… so what's it like to use Fail2ban with pf on FreeBSD? +

+ +

+Firstly, Fail2ban uses a jail system, not the same as the jail system provided in FreeBSD, in which IPs can no longer access a service monitored by Fail2ban once their IP is banned. However, there's almost no good information out there to use Fail2ban with pf on FreeBSD! Sure, our SysAdmin Team found setup guides and we followed those to the absolute T, but boy was it a headache for us to do it… Okay, great, now we've got the Fail2ban up and running, added as a service to rc… And nobody's getting blocked. Why? +

+
+ +
+
+
+
+

Failed2ban At All

+
+

+We weren't really able to conclusively figure out as to what was going wrong with Fail2ban, but our presumption had to do with pf somehow, or with our Fail2ban configuration. We'd found before in FreeBSD's forums1 a link to using Fail2ban bans with pf on a fairly helpful FreeBSD-centric blog2 and, huh… Fail2ban was trying to use iptables. What? That's so weird! We did almost everything identically to this blog's config too! We even overrid the Fail2ban config defaults to say "Hey, when you're banning an IP, PLEASE use pf to do this! Thanks!" But alas, IPs were not being banned. It worked when we sat there and added these IPs to the banlist ourselves using Fail2ban manually, but not automatically. Hm, odd. +

+ +

+This was a massive problem that we immediately had to take to the CISO. We have a bruteforce prevention system, and it isn't even working after we set it up correctly, this is not good! It was decided among the SysAdmins and Network Engineers that we were going to completely migrate over to blacklistd to properly enforce our IP bans, or that was the hope. In all honesty, we were afraid that this system wouldn't work either, or it'd be esoteric. This was our security we were gambling on here! But, did we really have a reason to be afraid? +

+
+ +
+
+
+
+

Get Blacklisted!

+
+

+So what even is blacklistd? Well, in versions of FreeBSD prior to 15, blacklistd is a similar service to Fail2ban but provided natively in FreeBSD to do the same task. While Fail2ban is in Python, blacklistd is in C, which has far superior performance with a much smaller resource footprint, something we absolutely loved! A lot of the code in blacklistd also comes from NetBSD's blocklistd, and blocklistd is now what the daemon is called in FreeBSD 15; and surprisingly this was a hell of a simple system for us to setup. Firstly, the config is dead simple in contrast to Fail2ban, we just added an anchor for it to our pf.conf and modified the blacklistd.conf to increase the bantime and change the maximum number of tries. The OS even provided a fantastic and sane example config that required very little work from us to tweak! After that, we enabled it in the init system, enabled it in our sshd_config, and restarted everything. +

+ +

+Immediately, blacklistd got to work. Specifically, unlike Fail2ban, IPs got banned. Shot down right then and there after meeting blacklistd's ban criteria! We started to see immediate results. I really do mean immediate. IPs were already starting to get shot down by blacklistd and added to the pf table. It was a serious boost to our peace of mind, and quite wild how little work it took to actually start blacklisting IPs trying to bruteforce SSH. Now of course, it goes without saying that blacklistd works at the socket level, it's a system that works between Layers 3 and 4 upon direct socket data whereas Fail2ban merely greps logfiles and acts upon events, meaning it's acting upon Layer 7 data to then make Layer 3 and 4 decisions.1 There are cases where Fail2ban might be the choice and blacklistd isn't, such as services running in Jails that blacklistd then cannot monitor if you're attempting to run a singular firewall system. It does go without saying though, that blacklistd as an SSH intrusion prevention system is phenomenally simpler on FreeBSD with pf than Fail2ban is. How simple is simple though? +

+
+ +
+
+
+
+

Try It Yourself!

+
+

+It's amazing how quick it is to get blacklistd with a simple enough configuration running on a FreeBSD system using pf. First, let's say that your /etc/pf.conf looks something like this: +

+ +
+
set block-policy drop
+set skip on lo0
+scrub in
+
+block in log on iface0 all
+pass in quick log on iface0 proto tcp from any to any 22 keep state
+pass in quick on iface0 inet proto icmp icmp-type { echoreq, unreach, timex } keep state
+pass out quick log on iface0 proto { tcp, udp, icmp } from any to any keep state
+
+
+ +

+So we've got our SSH port open in pf, but inherently that is not going to simply stop bruteforcing. This just means every other port is going to have packets sent to it dropped (since the block-policy is set to drop). We have to first add in the anchor for blacklistd into our /etc/pf.conf: +

+ +
+
set block-policy drop
+set skip on lo0
+scrub in
+
+anchor "blacklistd/*" in on iface0
+
+block in log on iface0 all
+pass in quick log on iface0 proto tcp from any to any 22 keep state
+pass in quick on iface0 inet proto icmp icmp-type { echoreq, unreach, timex } keep state
+pass out quick log on iface0 proto { tcp, udp, icmp } from any to any keep state
+
+
+ +

+Great, now we can go setup our /etc/blacklistd.conf. There is surprisingly not a whole ton we need to do, because FreeBSD 14.3 out the box gives us a great starting point for our blacklistd rules, we can just change some of the ban lengths and attempts: +

+ +
+
#
+# Blacklist rule
+# adr/mask:port type    proto   owner           name    nfail   disable
+[local]
+ssh             stream  tcp     *               *       3       24h
+
+
+ +

+The nfail option is just specifying how many failed login attempts until blacklistd gets triggered, and the disable option is how long the ban lasts. Any rules set under [local] are in regards to locally ran services from the system and thus how they get handled by blacklistd.3 Now that we've created our blacklistd rules, let's go into /etc/ssh/sshd_config and set UseBlacklist yes to start using blacklistd, then add blacklistd_enable"YES"= to our /etc/rc.conf. Now restart sshd, start blacklistd, and run pfctl -f /etc/pf.conf to reload your new firewall rules and you've got blacklistd running! Surprisingly simpler than using Fail2ban, and trust us… we jumped through too many hoops with that… +

+ +

+I don't expect this to have been an eye-opening or profound entry, but it's a worthwhile writeup for any aspiring FreeBSD SysAdmins and Engineers to look at when using real FreeBSD systems in real production environments when weighing out how best to handle their security posture. Until then, stay safe on the internet and always better to be safe rather than sorry! +

+
+ +
+
+
+ +
+ + diff --git a/blog/failed2ban.org b/blog/failed2ban.org new file mode 100644 index 0000000..819540d --- /dev/null +++ b/blog/failed2ban.org @@ -0,0 +1,103 @@ +#+title: Failed2ban - A Real Test In The Trenches +#+date: 2026-02-21 +#+author: Buckwheat + +#+options: html-postamble:nil html-preamble:nil num:nil title:nil toc:nil +#+HTML_HEAD: + +#+HTML:
+[[https://buckwheat.neocities.org/blog/posts][Click here to return to blog posts menu]] +#+HTML:
+ +#+TOC: headlines + +#+HTML:
+#+ATTR_HTML: :style height:100%;width:100%;object-fit:contain; +[[./images/failed2ban.png]] +#+HTML:
+ +#+HTML:
+* Intro +Hey! It's been a while since there's been activity, huh? Well, worth first saying (even if almost 2 months late) Happy New Years to all my readers. + +I recently became a founding member of a multinational group of FOSS Developers and Advocates called Neo-Sekai Club (more about that in a future post of mine!), and I'm in charge of many, many tasks, System Administration and Network Engineer being two of these tasks. In this blogpost, I go over real boots-on-the-ground experience of trying Fail2ban on production FreeBSD servers used by Neo-Sekai Club to see whether the thing everyone uses is really always the thing that works! +#+HTML:
+ +#+HTML:
+* The Battlefield +It goes without saying that the moment your server touches the internet, you're going to start having script kiddies and botnets hammering on your SSH, firing off port scans, and all sorts of other things. This totally sucks, and this is why we use firewalls. At Neo-Sekai Club, we deploy all of our servers using only BSDs. In this on-the-ground test, this is from real experience using a FreeBSD 14.3 server that we host our web services from. + +We use Packet Filter (pf) as our firewall, which is a fantastically simple firewall ported over from OpenBSD and is just as much of a breeze to use over on FreeBSD. Packets get scrubbed in on our interface, logged out to the pflog, and if that's not a port we've whitelisted in the firewall, we block it. Pretty simple system to use! However, that's just not enough in a real-world scenario when it comes to SSH bruteforce attempts. If this was a Linux server, here's now where we're getting into using a system like Fail2ban. So... what exactly is Fail2ban? +#+HTML:
+ +#+HTML:
+* Enter Fail2ban +Fail2ban is a Python-based security system that integrates into your firewall and provides an IP blacklist based on a number of failed SSH attempts within an alloted timeframe, and then issues bans on IPs who've failed SSH enough times for a period specified by the System Administrator. In the World of Linux, this is a very common anti-bruteforce system that System Administrators use to stop bruteforce attacks in their tracks, and it integrates quite nicely into Linux's firewall system iptables. Here's the thing however, we're not on Linux, and we don't get to use iptables on FreeBSD... so what's it like to use Fail2ban with pf on FreeBSD? + +Firstly, Fail2ban uses a jail system, not the same as the jail system provided in FreeBSD, in which IPs can no longer access a service monitored by Fail2ban once their IP is banned. However, there's almost no good information out there to use Fail2ban with pf on FreeBSD! Sure, our SysAdmin Team found setup guides and we followed those to the absolute T, but boy was it a headache for us to do it... Okay, great, now we've got the Fail2ban up and running, added as a service to rc... And nobody's getting blocked. Why? +#+HTML:
+ +#+HTML:
+* Failed2ban At All +We weren't really able to conclusively figure out as to what was going wrong with Fail2ban, but our presumption had to do with pf somehow, or with our Fail2ban configuration. We'd found before in FreeBSD's forums[fn:1] a link to using Fail2ban bans with pf on a fairly helpful FreeBSD-centric blog[fn:2] and, huh... Fail2ban was trying to use iptables. What? That's so weird! We did almost everything identically to this blog's config too! We even overrid the Fail2ban config defaults to say "Hey, when you're banning an IP, PLEASE use pf to do this! Thanks!" But alas, IPs were not being banned. It worked when we sat there and added these IPs to the banlist ourselves using Fail2ban manually, but not automatically. Hm, odd. + +This was a massive problem that we immediately had to take to the CISO. We have a bruteforce prevention system, and it isn't even working after we set it up correctly, this is not good! It was decided among the SysAdmins and Network Engineers that we were going to completely migrate over to blacklistd to properly enforce our IP bans, or that was the hope. In all honesty, we were afraid that this system wouldn't work either, or it'd be esoteric. This was our security we were gambling on here! But, did we really have a reason to be afraid? +#+HTML:
+ +#+HTML:
+* Get Blacklisted! +So what even is blacklistd? Well, in versions of FreeBSD prior to 15, blacklistd is a similar service to Fail2ban but provided natively in FreeBSD to do the same task. While Fail2ban is in Python, blacklistd is in C, which has far superior performance with a much smaller resource footprint, something we absolutely loved! A lot of the code in blacklistd also comes from NetBSD's blocklistd, and blocklistd is now what the daemon is called in FreeBSD 15; and surprisingly this was a hell of a simple system for us to setup. Firstly, the config is dead simple in contrast to Fail2ban, we just added an anchor for it to our =pf.conf= and modified the =blacklistd.conf= to increase the bantime and change the maximum number of tries. The OS even provided a fantastic and sane example config that required very little work from us to tweak! After that, we enabled it in the init system, enabled it in our =sshd_config=, and restarted everything. + +Immediately, blacklistd got to work. Specifically, unlike Fail2ban, IPs got *banned*. Shot down right then and there after meeting blacklistd's ban criteria! We started to see immediate results. I really do mean *immediate*. IPs were already starting to get shot down by blacklistd and added to the pf table. It was a serious boost to our peace of mind, and quite wild how little work it took to actually start blacklisting IPs trying to bruteforce SSH. Now of course, it goes without saying that blacklistd works at the socket level, it's a system that works between Layers 3 and 4 upon direct socket data whereas Fail2ban merely greps logfiles and acts upon events, meaning it's acting upon Layer 7 data to then make Layer 3 and 4 decisions.[fn:1] There are cases where Fail2ban might be the choice and blacklistd isn't, such as services running in Jails that blacklistd then cannot monitor if you're attempting to run a singular firewall system. It does go without saying though, that blacklistd as an SSH intrusion prevention system is phenomenally simpler on FreeBSD with pf than Fail2ban is. How simple is simple though? +#+HTML:
+ +#+HTML:
+* Try It Yourself! +It's amazing how quick it is to get blacklistd with a simple enough configuration running on a FreeBSD system using pf. First, let's say that your =/etc/pf.conf= looks something like this: + +#+begin_src +set block-policy drop +set skip on lo0 +scrub in + +block in log on iface0 all +pass in quick log on iface0 proto tcp from any to any 22 keep state +pass in quick on iface0 inet proto icmp icmp-type { echoreq, unreach, timex } keep state +pass out quick log on iface0 proto { tcp, udp, icmp } from any to any keep state +#+end_src + +So we've got our SSH port open in pf, but inherently that is not going to simply stop bruteforcing. This just means every other port is going to have packets sent to it dropped (since the block-policy is set to drop). We have to first add in the anchor for blacklistd into our =/etc/pf.conf=: + +#+begin_src +set block-policy drop +set skip on lo0 +scrub in + +anchor "blacklistd/*" in on iface0 + +block in log on iface0 all +pass in quick log on iface0 proto tcp from any to any 22 keep state +pass in quick on iface0 inet proto icmp icmp-type { echoreq, unreach, timex } keep state +pass out quick log on iface0 proto { tcp, udp, icmp } from any to any keep state +#+end_src + +Great, now we can go setup our =/etc/blacklistd.conf=. There is surprisingly not a whole ton we need to do, because FreeBSD 14.3 out the box gives us a great starting point for our blacklistd rules, we can just change some of the ban lengths and attempts: + +#+begin_src +# +# Blacklist rule +# adr/mask:port type proto owner name nfail disable +[local] +ssh stream tcp * * 3 24h +#+end_src + +The nfail option is just specifying how many failed login attempts until blacklistd gets triggered, and the disable option is how long the ban lasts. Any rules set under =[local]= are in regards to locally ran services from the system and thus how they get handled by blacklistd.[fn:3] Now that we've created our blacklistd rules, let's go into =/etc/ssh/sshd_config= and set =UseBlacklist yes= to start using blacklistd, then add =blacklistd_enable="YES"= to our =/etc/rc.conf=. Now restart =sshd=, start =blacklistd=, and run =pfctl -f /etc/pf.conf= to reload your new firewall rules and you've got blacklistd running! Surprisingly simpler than using Fail2ban, and trust us... we jumped through too many hoops with that... + +I don't expect this to have been an eye-opening or profound entry, but it's a worthwhile writeup for any aspiring FreeBSD SysAdmins and Engineers to look at when using real FreeBSD systems in real production environments when weighing out how best to handle their security posture. Until then, stay safe on the internet and always better to be safe rather than sorry! +#+HTML:
+ +#+HTML:
+[fn:1] [[https://forums.freebsd.org/threads/fail2ban-1-1-x-with-pf-need-help-before-i-lose-it-where-to-find-docs-or-examples.98862/][The FreeBSD Forums Post]] +[fn:2] [[https://dbdemon.com/pf_and_fail2ban/][dbdemon's Blog Post About Fail2ban and pf]] +[fn:3] [[https://man.freebsd.org/cgi/man.cgi?query=blacklistd.conf&apropos=0&sektion=5&manpath=FreeBSD+14.3-RELEASE&format=html][FreeBSD 14.3 Man Page for blacklistd.conf]] +#+HTML:
diff --git a/blog/images/failed2ban.png b/blog/images/failed2ban.png new file mode 100644 index 0000000..797ff3d Binary files /dev/null and b/blog/images/failed2ban.png differ diff --git a/blog/posts.html b/blog/posts.html new file mode 100644 index 0000000..9512c64 --- /dev/null +++ b/blog/posts.html @@ -0,0 +1,219 @@ + + + + + + + +Blog posts + + + + + + +
+
+

+Click here to return to the homepage +

+
+ +
+ +
+
+ + diff --git a/blog/posts.org b/blog/posts.org new file mode 100644 index 0000000..df4eb02 --- /dev/null +++ b/blog/posts.org @@ -0,0 +1,17 @@ +#+title: Blog posts +#+date: 2025-11-19 +#+author: Buckwheat + +#+options: html-postamble:nil html-preamble:nil num:nil title:nil toc:nil +#+HTML_HEAD: + +#+HTML:
+[[https://buckwheat.neocities.org/][Click here to return to the homepage]] +#+HTML:
+ +#+HTML:
+* My blog posts + +[[https://buckwheat.neocities.org/blog/failed2ban.html][02/21/2026: Failed2ban - A Real Test In The Trenches]] + +#+HTML:
diff --git a/index.html b/index.html new file mode 100644 index 0000000..e541d06 --- /dev/null +++ b/index.html @@ -0,0 +1,263 @@ + + + + + + + +Welcome to my site! + + + + + + +
+
+
+

Hello there!

+
+ +
+

buckwheat.jpg +

+
+ +

+Welcome! This is my personal blog! Here I write about all of the things that interest me like Cyber Security, Systems Programming, UNIX/Linux, and anything tech adjacent! +

+ +

+You can view my blog postings here! +

+
+ +
+
+
+

Who are you?

+
+

+You can go read my About Me to figure out who I am! +

+
+ +
+
+
+
+

This site is bare bones right now, and your HTML code looks weird! Why is that?

+
+

+I know how to write HTML and CSS, and I even know how to write JavaScript and more! But, it's really annoying for me to do so, and for something like running my own blog? I really rather not do that. Since Neocities is a static site provider, I decided I didn't really need any of that fancy stuff. +

+ +

+I instead use my trusty editor Emacs to make my pages of my website using the org-mode plugin by writing an .org file first and then exporting it to .html! It makes writing my site easier to use my Emacs, and if you aren't using Emacs, why? It's a fantastic tool! +

+
+ +
+
+
+
+

What is this CSS theme you're using?

+
+

+This is a theme I call Tokyo Night, based off the popular colour scheme seen in text editors. The base CSS is a modification of thomasf's solarized-dark theme. +

+ +

+You can download his colour theme from GitHub here! +

+
+
+
+
+
+ + diff --git a/index.org b/index.org new file mode 100644 index 0000000..1c05aa4 --- /dev/null +++ b/index.org @@ -0,0 +1,37 @@ +#+title: Welcome to my site! +#+date: 2025-11-19 +#+author: Buckwheat + +#+options: html-postamble:nil html-preamble:nil num:nil title:nil toc:nil +#+HTML_HEAD: + +#+HTML:
+ +* Hello there! + +#+ATTR_HTML: :style border-radius:50%; +[[./assets/buckwheat.jpg]] + +Welcome! This is my personal blog! Here I write about all of the things that interest me like Cyber Security, Systems Programming, UNIX/Linux, and anything tech adjacent! + +[[https://buckwheat.neocities.org/blog/posts.html][You can view my blog postings here!]] +#+HTML:
+ +#+HTML:
+** Who are you? +You can go read my [[https://buckwheat.neocities.org/about_me][About Me]] to figure out who I am! +#+HTML:
+ +#+HTML:
+** This site is bare bones right now, and your HTML code looks weird! Why is that? +I know how to write HTML and CSS, and I even know how to write JavaScript and more! But, it's really annoying for me to do so, and for something like running my own blog? I really rather not do that. Since Neocities is a static site provider, I decided I didn't really need any of that fancy stuff. + +I instead use my trusty editor Emacs to make my pages of my website using the org-mode plugin by writing an .org file first and then exporting it to .html! It makes writing my site easier to use my Emacs, and if you aren't using Emacs, why? It's a fantastic tool! +#+HTML:
+ +#+HTML:
+** What is this CSS theme you're using? +This is a theme I call Tokyo Night, based off the popular colour scheme seen in text editors. The base CSS is a modification of thomasf's solarized-dark theme. + +[[https://github.com/thomasf/solarized-css][You can download his colour theme from GitHub here!]] +#+HTML:
diff --git a/not_found.html b/not_found.html new file mode 100644 index 0000000..a31a550 --- /dev/null +++ b/not_found.html @@ -0,0 +1,216 @@ + + + + + + + +Error 404 - Page Not Found + + + + + + +
+
+
+

Oh no!

+
+

+The page you requested cannot be found! It must've either been deleted or it didn't exist in the first place! +

+ +

+Click here to return to the index page! +

+
+
+
+
+ + diff --git a/not_found.org b/not_found.org new file mode 100644 index 0000000..39b5b87 --- /dev/null +++ b/not_found.org @@ -0,0 +1,13 @@ +#+title: Error 404 - Page Not Found +#+date: 2025-11-19 +#+author: Buckwheat + +#+options: html-postamble:nil html-preamble:nil num:nil title:nil toc:nil +#+HTML_HEAD: + +#+HTML:
+* Oh no! +The page you requested cannot be found! It must've either been deleted or it didn't exist in the first place! + +[[https://buckwheat.neocities.org/][Click here to return to the index page!]] +#+HTML: