<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>fail2ban &#8211; Blog of Kliment Andreev &#8211; A place so I won&#039;t forget things</title>
	<atom:link href="https://blog.andreev.it/tag/fail2ban/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.andreev.it</link>
	<description></description>
	<lastBuildDate>Tue, 14 Jul 2020 14:29:40 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
	<item>
		<title>CentOS, FreeBSD: Secure SSH with fail2ban and blacklistd with MFA (Google Authenticator)</title>
		<link>https://blog.andreev.it/2020/03/centos-freebsd-secure-ssh-with-fail2ban-and-blacklistd-with-mfa-google-authenticator/</link>
					<comments>https://blog.andreev.it/2020/03/centos-freebsd-secure-ssh-with-fail2ban-and-blacklistd-with-mfa-google-authenticator/#respond</comments>
		
		<dc:creator><![CDATA[Kliment Andreev]]></dc:creator>
		<pubDate>Fri, 27 Mar 2020 18:57:52 +0000</pubDate>
				<category><![CDATA[CentOS]]></category>
		<category><![CDATA[FreeBSD]]></category>
		<category><![CDATA[blacklistd]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[fail2ban]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[Google Authenticator]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[MFA]]></category>
		<guid isPermaLink="false">https://blog.andreev.it/?p=6612</guid>

					<description><![CDATA[I have some servers that are exposed to the Internet on port 22 and&#8230;]]></description>
										<content:encoded><![CDATA[<div id="bsf_rt_marker"></div><p>I have some servers that are exposed to the Internet on port 22 and I see a lot of brute force attacks coming. The easiest and best way to protect is to block port 22 for everyone except a handful of IPs or safe subnets. But sometimes, these servers need to be available for some other people who work from who knows where, so you can&#8217;t just restrict IPs anymore. In this case, the best practice is to enforce MFA (multi factor authentication). But, this won&#8217;t work if you have some service accounts that need to log to the server. You can&#8217;t MFA a service account.To balance between security and availability, you can also install some tools that will block the repeated offenders, IPs that crawl the network and try to login to your network over SSH. In this post I&#8217;ll describe how to use fail2ban for CentOS and blacklistd for FreeBSD. fail2ban for FreeBSD is too complex to setup while blacklistd is a native tool and does the same job. </p>
<h1>CentOS</h1>
<p>I have a CentOS box with both <strong>SELinux </strong>and <strong>firewalld </strong>enabled. I am not using keys to log to the server, I have a generic user that uses password and the root is NOT allowed to log to the server using ssh (<strong>PermitRootLogin no in /etc/ssh/sshd_config</strong>).</p>
<h2>Log with SSH keys (optional)</h2>
<p>If you want to have some users that need to log with SSH keys, you have to do the following. Log as that user and run <strong>ssh-keygen</strong> and hit enter for the defaults.</p>
<pre class="brush: bash; highlight: [1,3,5,6]; title: ; notranslate">
ssh-keygen -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test/.ssh/id_rsa):
Created directory '/home/test/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/test/.ssh/id_rsa.
Your public key has been saved in /home/test/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:CmYzEZq7u4IilphSEC/cdTFKQY2+fjQgkw8acCXZjIo test@localhost.localdomain
The key's randomart image is:
+---&#x5B;RSA 4096]----+
|  .*+++o.        |
|o ++++.o.        |
|+=+ =..          |
|Eo.B +           |
| o+ @ o S        |
| ..+ * +         |
|ooo . o .        |
|Oo . . .         |
|=.o.  .          |
+----&#x5B;SHA256]-----+
</pre>
<p>You have two files created for the <strong>test </strong>user, a private (<strong>id_rsa</strong>) and a public (<strong>id_rsa.pub</strong>) file.<br />
You need the private file in order to use it with putty. But putty uses it&#8217;s own PPK file, so you have to convert that with <a href="https://www.puttygen.com/convert-pem-to-ppk">puttygen</a>. You can use the Windows version or you can install putty and convert it. <strong>NOTE</strong>: putty is a GUI program so don&#8217;t install it on a server because it will install a bunch of GUI libraries.<br />
Install epel-release repo.</p>
<pre class="brush: bash; title: ; notranslate">
yum install -y epel-release
</pre>
<p>&#8230;and then install putty.</p>
<pre class="brush: bash; title: ; notranslate">
yum install -y putty
</pre>
<p>Log as the user and convert the file from PEM to PPK. </p>
<pre class="brush: bash; title: ; notranslate">
puttygen .ssh/id_rsa -o private.ppk -O private
</pre>
<p>Your key will be in the home directory as <strong>private.ppk</strong>. Use this key to log to your server. But, you have to authorize your public key first. Logged as test user do:</p>
<pre class="brush: bash; title: ; notranslate">
cat .ssh/id_rsa.pub &gt;&gt; .ssh/authorized_keys
chmod 0600 .ssh/authorized_keys
</pre>
<p>Now, you can log as test user with a key using putty. This will affect only the <strong>test </strong>user to log with a key. The other users will continue logging as they used to do before. Mind that at this point you can log as a test user using a key and the password. If you want to completely disable password logins make sure that these settings are configured under <strong>/etc/ssh/sshd_config</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
</pre>
<p>Restart sshd (<strong>systemctl restart sshd</strong>) anytime you make a change in that file.</p>
<h2>Google Authenticator</h2>
<p>In order to enable MFA, we&#8217;ll have to install Google Authenticator on the server and a client on a phone or a desktop. I use <a href="https://authy.com/" rel="noopener noreferrer" target="_blank">authy </a>for that. You can use any MFA client you want on your phone. I will also use key only logins and no passwords so go ahead and change those 3 lines above in <strong>sshd_config</strong>.  Also, make sure that you can login with at least one user that can sudo or you&#8217;ll be locked. The only way to get in will be thru the console which does not use ssh so it&#8217;s not affected.<br />
To install Google Authenticator, you need the epel repo. Skip this step if you already completed any of the previous steps.</p>
<pre class="brush: bash; title: ; notranslate">
yum install -y epel-release
</pre>
<p>Then install Google Authenticator.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install google-authenticator
</pre>
<p>Now, you can go two ways. Mandate that all accounts use MFA or only certain ones. It depends on your server usage case. If you have some automated scripts that use SSH to do some work, the first option is not viable. For each account that you want to use MFA, you have to configure the authenticator. I&#8217;ll use my <strong>test </strong>account. Logged as the test user, type <strong>google-authenticator</strong>. I answered <strong>y</strong> on all of the questions. </p>
<pre class="brush: bash; highlight: [1,2,15,19,30,35]; title: ; notranslate">
google-authenticator
Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/test@localhost.l....
                                                                                
Your new secret key is: HF52123FWAGRKLGX5EJ4567CLE
Your verification code is 880933
Your emergency scratch codes are:
  94310385
  95472197
  98736692
  31351434
  83561212

Do you want me to update your &quot;/home/test/.google_authenticator&quot; file? (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y
</pre>
<p>In a console session you&#8217;ll see a barcode but it&#8217;s garbled. Instead scroll up and you&#8217;ll see a URL (line 4). Go to that URL and scan the barcode with your MFA app.<br />
Open <strong>/etc/ssh/sshd_config</strong>, scroll all the way down and add this line as the last line.</p>
<pre class="brush: bash; title: ; notranslate">
AuthenticationMethods publickey,password publickey,keyboard-interactive
</pre>
<p>Then change this line to <strong>yes</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
ChallengeResponseAuthentication yes
</pre>
<p>Edit <strong>/etc/pam.d/sshd</strong> and after these two lines, add the <strong>auth </strong>line.</p>
<pre class="brush: bash; highlight: [3]; title: ; notranslate">
# Used with polkit to reauthorize users in remote sessions
-session   optional     pam_reauthorize.so prepare
auth required pam_google_authenticator.so nullok
</pre>
<p><strong>nullok </strong>means that you are allowing some accounts to log as usual, without MFA. If you remove <strong>nullok</strong>, all accounts will be required to use MFA.<br />
Also, comment this line like this.</p>
<pre class="brush: bash; title: ; notranslate">
#auth       substack     password-auth
</pre>
<p>Restart the <strong>sshd </strong>daemon now.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl restart sshd
</pre>
<p>At this point, you&#8217;ll be able to login only with a public key and an MFA for the users that have google-authenticator and a public key configured. The password users won&#8217;t be able to log in. The console logins are not affected. So, if you have some users without a public key and google-authneticator, they&#8217;ll still be able to login with a password from a console.</p>
<h2>fail2ban</h2>
<p>In order to install <a href="https://www.fail2ban.org/wiki/index.php/Main_Page" rel="noopener noreferrer" target="_blank">fail2ban </a>you have to install the <strong>epel-release</strong> first. Skip this step if you followed the previous step because you already installed epel repo.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install epel-release
</pre>
<p>Then install fail2ban.</p>
<pre class="brush: bash; title: ; notranslate">
yum -y install fail2ban
</pre>
<p>Make sure it starts on boot.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl enable fail2ban
</pre>
<p>The config files for fail2ban are under <strong>/etc/fail2ban</strong>, but you shouldn&#8217;t change any of the existing files. Instead create a new file called <strong>sshd.conf</strong> under <strong>/etc/fail2ban/jail.d</strong> directory. Here is mine.</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;sshd]
enabled = true

# &quot;ignoreip&quot; can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
# will not ban a host which matches an address in this list. Several addresses
# can be defined using space (and/or comma) separator.
ignoreip = 127.0.0.1/8

# &quot;bantime&quot; is the number of seconds that a host is banned.
# add m for minutes or hr for hours
bantime  = 10m

# A host is banned if it has generated &quot;maxretry&quot; during the last &quot;findtime&quot;
# seconds.
findtime = 300

# &quot;maxretry&quot; is the number of failures before a host get banned.
maxretry = 3
</pre>
<p>It is very self explanatory with the included comments. In my example, I&#8217;ll ban an IP for 10 minutes if I see that IP try and fail 3 times to login in 300 seconds (5 mins). You can start/restart the service now.</p>
<pre class="brush: bash; title: ; notranslate">
systemctl start fail2ban
</pre>
<p>The fail2ban log file is under <strong>/var/log/fail2ban.log</strong> and the SSH logs are under <strong>/var/log/secure</strong>.<br />
Most of the hits that you&#8217;ll see in the <strong>/var/log/secure</strong> are IPs that will try to log as admin or root, but only once in a hour or two. So, they won&#8217;t be caught with these settings. You should add all of your subnets under <strong>ignoreip </strong>setting and change the <strong>maxretry </strong>to 1 and <strong>bantime </strong>to 8760h (1 year). It will ultimately block the IP for a year for anyone that makes any unauthorized attempt. It&#8217;s up to you what settings you use.<br />
Here is an example in the <strong>/var/log/secure</strong> of an IP (3.92.82.165) trying to log as root.</p>
<pre class="brush: bash; title: ; notranslate">
Mar 21 10:26:13 localhost sshd&#x5B;13207]: pam_succeed_if(sshd:auth): requirement &quot;uid &gt;= 1000&quot; not met by user &quot;root&quot;
Mar 21 10:26:15 localhost sshd&#x5B;13207]: Failed password for root from 3.92.82.165 port 60362 ssh2
Mar 21 10:26:16 localhost unix_chkpwd&#x5B;13211]: password check failed for user (root)
Mar 21 10:26:16 localhost sshd&#x5B;13207]: pam_succeed_if(sshd:auth): requirement &quot;uid &gt;= 1000&quot; not met by user &quot;root&quot;
Mar 21 10:26:18 localhost sshd&#x5B;13207]: Failed password for root from 3.92.82.165 port 60362 ssh2
Mar 21 10:26:18 localhost sshd&#x5B;13207]: Connection closed by 3.92.82.165 port 60362 &#x5B;preauth]
Mar 21 10:26:18 localhost sshd&#x5B;13207]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=ec2-3-92-82-165.compute-1.amazonaws.com  user=root
</pre>
<p>&#8230;and the IP got banned. You can see that from /var/log/fail2ban.</p>
<pre class="brush: bash; title: ; notranslate">
2020-03-21 10:26:12,259 fail2ban.filter         &#x5B;13131]: INFO    &#x5B;sshd] Found 3.92.82.165 - 2020-03-21 10:26:12
2020-03-21 10:26:15,382 fail2ban.filter         &#x5B;13131]: INFO    &#x5B;sshd] Found 3.92.82.165 - 2020-03-21 10:26:15
2020-03-21 10:26:18,887 fail2ban.filter         &#x5B;13131]: INFO    &#x5B;sshd] Found 3.92.82.165 - 2020-03-21 10:26:18
2020-03-21 10:26:19,286 fail2ban.actions        &#x5B;13131]: NOTICE  &#x5B;sshd] Ban 3.92.82.165
</pre>
<p>You can also see the banned IPs using this command. <strong>sshd </strong>is the name of the jail. If you scroll up, you&#8217;ll see that I named my jail like that <strong>[sshd]</strong> in the conf file above.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     8
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 2
   |- Total banned:     2
   `- Banned IP list:   3.81.85.240 3.92.82.165
</pre>
<p>But mistakes happen. If someone gets banned, you can unban the IP with this command, where sshd is the jail name and the IP you want unbanned.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
fail2ban-client set sshd unbanip 3.92.82.165
1
</pre>
<p>You should get 1 as an output. Means OK, True. If you get 0, it means the IP wasn&#8217;t there. If you can&#8217;t see all banned IPs, do:</p>
<pre class="brush: bash; title: ; notranslate">
zgrep 'Ban' /var/log/fail2ban.log*
</pre>
<h1>FreeBSD</h1>
<p>I have a FreeBSD box with no firewall enabled for now. For the <strong>blacklistd </strong>part, I&#8217;ll use <strong>pf</strong>. If you use <strong>ipfirewall </strong>or <strong>ipfilter</strong>, then you have to find another guide. I am not using keys to log to the server, I have a generic user that uses password and the root is NOT allowed to log to the server using ssh (<strong>PermitRootLogin no</strong> in <strong>/etc/ssh/sshd_config</strong>).</p>
<h2>Log with SSH keys (optional)</h2>
<p>If you want to have some users that need to log with SSH keys, you have to do the following. Log as that user and run <strong>ssh-keygen</strong> and hit enter for the defaults.</p>
<pre class="brush: bash; highlight: [1,3,5]; title: ; notranslate">
ssh-keygen -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test/.ssh/id_rsa):
Created directory '/home/test/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/test/.ssh/id_rsa.
Your public key has been saved in /home/test/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:rT2m3a/KrC/jk1lxHUPMwuXM5g/5LpjkurrC29EO1z8 test@bsd.andreev.local
The key's randomart image is:
+---&#x5B;RSA 4096]----+
|                 |
|                 |
|           .     |
|        ..o o    |
|     . =S..+     |
|.   . + B+.      |
|o. o + @+.+o     |
|..o * o.OE+o     |
| ..o.+o.+@@.oo.  |
+----&#x5B;SHA256]-----+
</pre>
<p>You have two files created for the test user, a private (<strong>id_rsa</strong>) and a public (<strong>id_rsa.pub</strong>) file.<br />
You need the private file in order to use it with putty. But putty uses it&#8217;s own PPK file, so you have to convert that with <a href="https://www.puttygen.com/convert-pem-to-ppk">puttygen</a>. You can use the Windows version or you can install putty and convert it. </p>
<pre class="brush: bash; title: ; notranslate">
pkg install putty-nogtk
</pre>
<p>Log as the user and convert the file from PEM to PPK. </p>
<pre class="brush: bash; title: ; notranslate">
puttygen .ssh/id_rsa -o private.ppk -O private
</pre>
<p>Your key will be in the home directory as <strong>private.ppk</strong>. Use this key to log to your server. But, you have to authorize your public key first. Logged as test user do:</p>
<pre class="brush: bash; title: ; notranslate">
cat .ssh/id_rsa.pub &gt;&gt; .ssh/authorized_keys
chmod 0600 .ssh/authorized_keys
</pre>
<p>Now, you can log as test user with a key using putty. This will affect only the <strong>test </strong>user to log with a key. The other users will continue logging as they used to do before. Mind that at this point you can log as a test user using a key and the password. If you want to completely disable password logins make sure that these settings are configured under <strong>/etc/ssh/sshd_config</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
</pre>
<p>Restart sshd <strong>(service sshd restart)</strong>  anytime you make a change in that file.</p>
<h2>Google Authenticator</h2>
<p>In order to enable MFA, we&#8217;ll have to install Google Authenticator on the server and a client on a phone or a desktop. I use <a href="https://authy.com/" rel="noopener noreferrer" target="_blank">authy </a>for that. You can use any MFA client you want on your phone. I will also use key only logins and no passwords so go ahead and change those 3 lines above in <strong>sshd_config</strong>. Also, make sure that you can login with at least one user that can sudo or you’ll be locked. The only way to get in will be thru the console which does not use ssh so it’s not affected. To install Google Authenticator type:</p>
<pre class="brush: bash; title: ; notranslate">
pkg install pam_google_authenticator
</pre>
<p>Now, you can go two ways. Mandate that all accounts use MFA or only certain ones. It depends on your server usage case. If you have some automated scripts that use SSH to do some work, the first option is not viable. For each account that you want to use MFA, you have to configure the authenticator. I&#8217;ll use my <strong>test </strong>account. Logged as the test user, type <strong>google-authenticator</strong>. I answered <strong>y</strong> on all of the questions and <strong>-1</strong> to skip. </p>
<pre class="brush: bash; highlight: [1,2,6,15,19,30,35]; title: ; notranslate">
$ google-authenticator
Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/test@bsd.andreev.local%3Fsecret%3D24345SOFKCTVX44YXYZVYOQKCA%26issuer%3Dbsd.andreev.local                                                                                                                                                         
Your new secret key is: 24HJ3SOFKCTVZ33YVBKVYOKEDB
Enter code from app (-1 to skip): -1
Code confirmation skipped
Your emergency scratch codes are:
  34344229
  32681543
  80840666
  32593123
  29994070

Do you want me to update your &quot;/home/test/.google_authenticator&quot; file? (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y
</pre>
<p>In a console session you&#8217;ll see a barcode but it&#8217;s garbled. Instead scroll up and you&#8217;ll see a URL (line 4). Go to that URL and scan the barcode with your MFA app.<br />
Now, log as root or sudo to open <strong>/etc/ssh/sshd_config</strong> file. Change this line to <strong>yes</strong>. </p>
<pre class="brush: bash; title: ; notranslate">
ChallengeResponseAuthentication yes
</pre>
<p>Scroll all the way down and add this line as the last line.</p>
<pre class="brush: bash; title: ; notranslate">
AuthenticationMethods publickey,password publickey,keyboard-interactive
</pre>
<p>Edit <strong>/etc/pam.d/sshd</strong> and after these two lines, add the last <strong>auth </strong>line but commend the line above so it looks like this.</p>
<pre class="brush: bash; highlight: [3]; title: ; notranslate">
#auth           sufficient      pam_ssh.so              no_warn try_first_pass
#auth            required        pam_unix.so             no_warn try_first_pass
auth            required        pam_google_authenticator.so nullok
</pre>
<p><strong>nullok </strong>means that you are allowing some accounts to log as usual, without MFA. If you remove <strong>nullok</strong>, all accounts will be required to use MFA. Restart the <strong>sshd </strong>daemon now.</p>
<pre class="brush: bash; title: ; notranslate">
service sshd restart
</pre>
<p>At this point, you’ll be able to login only with a public key and an MFA for the users that have google-authenticator and a public key configured. The password users won’t be able to log in. The console logins are not affected. So, if you have some users without a public key and google-authneticator, they’ll still be able to login with a password from a console.<br />
If you don&#8217;t want to use public key and prefer passwords and MFA, then remove the last line from <strong>sshd_config AuthenticationMethod</strong>s and uncomment <strong>pam_unix.so</strong> in <strong>/etc/pam.d/sshd</strong> above <strong>google_authenticator</strong> line. Restart sshd.</p>
<h2>blacklistd</h2>
<p>fail2ban is available for FreeBSD, but it takes some time to configure it right with the proper firewalls. Instead, I use blacklistd which comes preinstalled. The only prerequisite is a firewall and I&#8217;ll be using pf for that. So, first let&#8217;s enable pf and blacklistd by adding these lines in <strong>/etc/rc.conf</strong>.</p>
<pre class="brush: bash; title: ; notranslate">
pf_enable=&quot;YES&quot;
pflog_enable=&quot;YES&quot;
blacklistd_enable=&quot;YES&quot;
blacklistd_flags=&quot;-r&quot;
</pre>
<p>Let&#8217;s create a very simple pf config file <strong>/etc/pf.conf</strong>.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
ext_if = &quot;vmx0&quot;
set skip on lo0
anchor &quot;blacklistd/*&quot; in on $ext_if
table &lt;blocked_subnets&gt; persist file &quot;/etc/blocked_subnets&quot;
block all
block in log quick on $ext_if from &lt;blocked_subnets&gt; to any
block out log quick on $ext_if from any to &lt;blocked_subnets&gt;
pass in on $ext_if proto tcp from any to any port {ssh} keep state
pass out quick on $ext_if keep state
</pre>
<p>Make sure you replace the name of your network card under line #1. You can get the name from <strong>ifconfig </strong>output. Also, if you want to block certain subnets by default, you can list them under <strong>/etc/blocked_subnets </strong>file. The subnet(s) should be in CIDR format. For example, if you want to block certain countries, you can look at this <a href="https://www.countryipblocks.net/acl.php" rel="noopener noreferrer" target="_blank">website</a>. BTW, the subnets blocking is part of pf not blacklistd. You can reboot now to make sure everything comes back OK and you are able to login. But before doing that, edit the <strong>sshd </strong>daemon and let it know that we&#8217;ll use <strong>blacklistd</strong>. Find <strong>UseBlacklist </strong>in <strong>/etc/ssh/sshd_conf</strong> and change it to:</p>
<pre class="brush: bash; title: ; notranslate">
UseBlacklist yes
</pre>
<p>The reboot will start pf and blacklistd. The blacklistd conf file is <strong>/etc/blacklistd.conf</strong>. You can read more about blacklistd <a href="https://www.freebsd.org/doc/handbook/firewalls-blacklistd.html" rel="noopener noreferrer" target="_blank">here</a>. For example, if I want to whitelist certain subnets from being blacklisted, I&#8217;ll add them under the <strong>[remote]</strong> section. In my case, I am whitelisting my home subnet and an external subnet.</p>
<pre class="brush: bash; title: ; notranslate">
&#x5B;remote]
172.16.1.0/24:ssh      *       *       *               =       *       *
154.21.3.0/24:ssh      *       *       *               =       *       *
</pre>
<p>You can see your SSH activity in <strong>/var/log/auth.log.</strong> To see who is blocked, run:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
blacklistctl dump -br
        address/ma:port id      nfail   remaining time
  213.74.176.36/32:22   OK      8/3     23h58m57s
</pre>
<p>This IP will be blocked for 24hrs by default. You can change that under the <strong>disable </strong>column in <strong>/etc/blacklistd.conf</strong>.<br />
You can also see the blocked IPs by looking at the pf <strong>blacklistd </strong>table.</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
pfctl -a blacklistd/22 -t port22 -T show
   213.74.176.36
</pre>
<p>And if you want to remove an IP or a subnet do:</p>
<pre class="brush: bash; highlight: [1]; title: ; notranslate">
pfctl -a blacklistd/22 -t port22 -T delete 213.74.176.36/32
1/1 addresses deleted.
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.andreev.it/2020/03/centos-freebsd-secure-ssh-with-fail2ban-and-blacklistd-with-mfa-google-authenticator/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
