cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

main: content/blog/2022-03-24-server-hardening.org · raw

  1#+date:        [2022-03-24 Thu 00:00:00]
  2#+title:       Server Hardening: Firewalls, SSH, VLANs
  3#+description: Hardening a home server with UFW, SSH config, fail2ban, and VLANs.
  4#+slug:        server-hardening
  5#+filetags:    :linux:security:
  6
  7* Planning Data Flows & Security
  8
  9** My Personal Data Flow
 10
 11#+begin_src
 12                                                          ┌───────┐   ┌─────────────────┐
 13                                                       ┌──► VLAN1 ├───► Private Devices │
 14                                                       │  └───────┘   └─────────────────┘
 15┌──────────┐   ┌────────┐   ┌──────────┐   ┌────────┐  │
 16│ Internet ├───► Router ├───► Firewall ├───► Switch ├──┤
 17└──────────┘   └────────┘   └──────────┘   └────────┘  │
 18                                                       │  ┌───────┐   ┌───────────────┐
 19                                                       └──► VLAN2 ├───► Public Server │
 20                                                          └───────┘   └───────────────┘
 21#+end_src
 22
 23** Thought Process
 24
 25To serve content from your home server and harden your security posture, you
 26have to think about the transport of data from =server= to =client=.
 27
 28Let's start with the actual server itself. Think about the following:
 29
 30- Do I have a firewall enabled? Do I need to update this to allow new ports or
 31  internet protocol (IP) addresses?
 32- Do I have an intrusion prevention system (IPS) or intrusion detection system
 33  (IDS) that may prevent outside traffic?
 34- Do I have any other security software installed?
 35- Are the services hosted inside Docker containers, behind a reverse proxy, or
 36  virtualized? If so, are they configured to allow outside traffic?
 37
 38Once the data leaves the server, where does it go? In my case, it goes to a
 39managed switch. In this case, I asked the following:
 40
 41- What configurations is the switch using?
 42- Am I using VLANs (virtual local area networks)?
 43  - Yes, I am using 802.1Q VLANs.
 44- Are the VLANs configured properly?
 45  - Yes, as shown in the Switch section below, I have a separate VLAN to allow
 46    outside traffic to and from the server alone. No other devices, except for a
 47    service port, and in that VLAN.
 48
 49At this point, the data has been processed through the switch. Where does it go
 50next? In my case, it's pretty simple: it goes to the router/modem device.
 51
 52- Does my internet service provider (ISP) block any ports that I need?
 53  - This is an important step that a lot of people run into when self-hosting at
 54    home. Use an online port-checker tool for your IP or call your ISP if you
 55    think ports are blocked.
 56- Is there a router firewall?
 57  - Yes, I checked that it's configured to allow the ports I need to run my
 58    services publicly. Common web servers and reverse proxies require ports 80
 59    and 443, but other services like media servers or games can require unique
 60    ports, so be sure to check the documentation for your service(s).
 61- Are there any other settings affecting inbound/outbound traffic?
 62  - Schedules or access blocks
 63  - Static Routing
 64  - QoS (Quality of Service)
 65  - Port Forwarding
 66  - DMZ (demilitarized zone) hosting
 67  - Remote Management (this can sometimes mess with services that also require
 68    the use of ports 80 and 443)
 69
 70Once the data leaves my router, it goes to the upstream ISP and can be accessed
 71publicly.
 72
 73*** Server
 74
 75The services I run on my server are installed straight into the operating system
 76(OS), without any use of Docker or virtual machines (VMs), so I don't need any
 77extra application configuration to make them accessible to the outside world.
 78
 79#+BEGIN_QUOTE
 80As of 2022-10-04, the paragraph above is no longer true as I now run a reverse
 81proxy with Nginx and host many services inside Docker. However, it doesn't
 82change anything regarding this post as I still just need to open ports 80 & 443
 83and create the necessary website configuration files.
 84#+END_QUOTE
 85
 86When creating new services - either installed directly on bare metal or within
 87something like Docker - I ensure that I read through the documentation
 88thoroughly to understand a few key things:
 89
 90- What network activities should this app perform (if any)? Using which ports
 91  and protocols?
 92- Does this app require any commands/services to be run as =root=?
 93- Does this app log errors, authentication failures/successes, or anything else
 94  that would be useful for an investigation?
 95
 96For extra security, I use limit all incoming connections to SSH connections
 97through my server firewall [=ufw= (Uncomplicated Firewall)] and disable common
 98SSH (Secure Shell Protocol) settings. After all of that, I use =fail2ban= as a
 99preventative measure against brute-force login attempts.
100
101As another piece of security, you can randomize your SSH port to ensure that
102random scanners or attackers can't easily try to force their way into your
103network. For example, you can edit the port rules in your server to block all
104connection requests to port =22= but forward all remote connections from port
105=12345= to your server's port =22=. Then you just need to SSH to your network
106via your randomized port.
107
108** =ufw=
109
110To see how to configure =ufw=, see my other post: [[https://cleberg.net/blog/ufw.html][Secure Your Network with the
111Uncomplicated Firewall]].
112
113The general notion with an on-device firewall is that you want to deny all
114incoming connections by default and then selectively open certain ports for
115services or users that you know need access.
116
117If you know that you will only be logging into this server from a certain set or
118list of IPs, you can always set the firewall to only allow connections to port
11922 from those IPs.
120
121For a quick start to only allow SSH connections to the server, use this:
122
123#+begin_src sh
124sudo ufw default deny incoming
125sudo ufw default allow outgoing
126sudo ufw allow 22
127sudo ufw enable
128#+end_src
129
130** =ssh=
131
1321. Using SSH Keys
133
134   First, make sure you have an SSH keypair generated on the device(s) that
135   you'll be using to log in to the server. If you don't have an SSH key, run
136   this command:
137
138   #+begin_src sh
139   ssh-keygen
140   #+end_src
141
142   Now that we have an SSH key, copy it to the server with the following
143   command, which will ask for the user's password before accepting the key:
144
145   #+begin_src sh
146   ssh-copy-id my_user@my_server
147   #+end_src
148
149   If you have multiple keys, you'll need to specify which to use. After it's
150   complete, =ssh= back into the server as that user and make sure it doesn't
151   ask for a password.
152
1532. Disable Password & Root Authentication
154
155   Now that we can access the server without a password, we will disable
156   password authentication and disable anyone from using =ssh= to login as
157   =root=.
158
159   To do this, open the =sshd_config= file:
160
161   #+begin_src sh
162   sudo nano /etc/ssh/sshd_config
163   #+end_src
164
165   You'll need to update the parameters to the values below. If one of these
166   rules is commented-out or doesn't exist, create the rule at the bottom of the
167   file.
168
169   #+begin_src config
170   PermitRootLogin no
171   PasswordAuthentication no
172   PubkeyAuthentication yes
173   #+end_src
174
175   Finally, restart the =ssh= service:
176
177   #+begin_src sh
178   sudo systemctl restart sshd.service
179   #+end_src
180
181   To test that everything's working so far, open ANOTHER terminal and try
182   logging in as =root= over SSH. It is very important that you keep your
183   current SSH session open and test with an additional session, or you will
184   lock yourself out at some point and will need to use a recovery method (e.g.,
185   hooking monitor up to home server) to get yourself back in.
186
1873. Enable Multi-Factor Authentication (MFA) for =ssh=
188
189   This part is optional, but I highly recommend it. So far, we've ensured that
190   no one can log into our user on the server without using our secret key, and
191   we've ensured that no one can log in remotely as =root=. Next, you can enable
192   MFA authentication for =ssh= connections.
193
194   This process involves editing a couple files and installing an MFA package,
195   so I will not include all the details in this post. To see how to configure
196   MFA for =ssh=, see my other post: [[https://cleberg.net/blog/ssh-mfa.html][Enabling MFA for SSH]].
197
198** =fail2ban=
199
200I haven't written a post on how I use =fail2ban=, but it's quite simple. I use
201the default =sshd= jail, but you can always create new jails for respective
202applications or ports. For example, if you use Nginx as your web server, you can
203use the =nginx-http-auth= jail.
204
205In order to get it up and running, use the following commands:
206
207#+begin_src sh
208sudo apt install fail2ban
209sudo fail2ban-client start sshd
210sudo fail2ban-client status sshd
211#+end_src
212
213This should be used as a last-resort defense and shouldn't be a replacement for
214the security measures mentioned above.
215
216* Switch
217
218Between the router and any local devices is my managed switch, which is used to
219create VLANs. The example below shows how I would isolate the VLANs if I were
220starting to host a single service at home.
221
222** 802.1Q VLAN Configuration
223
224In this configuration, port 8 is the public server that needs to be accessed
225from the outside. Port 23 is my 'dedicated service port' for this server. In
226order to SSH to this server, I need to plug my laptop into port 23 or else I
227cannot SSH. Otherwise, I'd need to hook up a monitor and keyboard directly to
228the server to manage it.
229
230| VLAN ID | VLAN Name | Member Ports | Tagged Ports | Untagged Ports |
231|---------+-----------+--------------+--------------+----------------|
232|       1 | Default   | 1-24         | 1-24         |                |
233|       2 | Server    | 1,8,23       | 1,8,23       |                |
234
235** 802.1Q VLAN PVID Setting
236
237Once the VLAN is created, I simply add the =VLAN ID= of =2= as the =PVID= for
238any related ports (in this case, see that ports =8= and =23= have a PVID of
239=2=).
240
241| Port | PVID |
242|------+------|
243|    1 |    1 |
244|    2 |    1 |
245|    3 |    1 |
246|    4 |    1 |
247|    5 |    1 |
248|    6 |    1 |
249|    7 |    1 |
250|    8 |    2 |
251|    9 |    1 |
252|   10 |    1 |
253|   11 |    1 |
254|   12 |    1 |
255|   13 |    1 |
256|   14 |    1 |
257|   15 |    1 |
258|   16 |    1 |
259|   17 |    1 |
260|   18 |    1 |
261|   19 |    1 |
262|   20 |    1 |
263|   21 |    1 |
264|   22 |    1 |
265|   23 |    2 |
266|   24 |    1 |
267
268* Router
269
270On my router, the configuration was as easy as opening the firewall settings and
271unblocking the ports I needed for my services (e.g., HTTP/S, Plex, SSH, MySQL,
272etc.).
273
274Since I'm relying on an ISP-provided modem/router combo for now (not by choice),
275I do not use any other advanced settings on my router that would inhibit any
276valid traffic to these services.
277
278The paragraph above regarding the ISP-owned router is no longer accurate as I
279now use the Ubiquiti Unifi Dream Machine Pro as my router. Within this router, I
280enabled port forwarding/firewall rules, segregate the network based on the
281device, and enable traffic restrictions (e.g., silently drop traffic from
282certain countries and threat categories).
283
284If you have the option with your ISP, I recommend using a personal router with
285software that you are familiar with so that you can explore all the options
286available to you.
287
288* Physical Security
289
290One large piece of self-hosting that people generally don't discuss online is
291physical security. However, physical security is very important for everyone who
292hosts a server like this. Exactly /how/ important it is depends on the server
293use/purpose.
294
295If you self-host customer applications that hold protected data, then physical
296security is extremely important and cannot be ignored. If you simply host a blog
297and some hobby sites, then it's a relatively minor consideration, but one you
298still need to think about.
299
300** Location
301
302The first consideration is quite simple: location.
303
304- Is the server within a property you own or housed on someone else's property?
305- Is it nearby (in your house, in your work office, in your neighbor's garage,
306  in a storage unit, etc.)?
307- Do you have 24/7 access to the server?
308- Are there climate considerations, such as humidity, fires, tornadoes,
309  monsoons?
310- Do you have emergency equipment nearby in case of emergency?
311
312** Hardware Ownership
313
314Secondly, consider the hardware itself:
315
316- Do you own the server in its entirety?
317- Are any other users able to access the server, even if your data/space is
318  segregated?
319- If you're utilizing a third party, do they have any documentation to show
320  responsibility? This could be a Service Organization Controls (SOC) 1/2/3
321  report, International Organization for Standardization (ISO) compliance
322  report, internal security/safety documentation.
323
324** Physical Controls
325
326Regardless of who owns the hardware, ensure that there are adequate safeguards
327in place, if necessary. These usually don't apply to small home servers and are
328usually covered already if you're utilizing a third party.
329
330These can include:
331
332- Server bezel locks
333- Server room locks - physical, digital, or biometric authentication
334- Security cameras
335- Raised floors/lowered ceilings with proper guards/gates in-place within the
336  floors or ceilings
337- Security personnel
338- Log sheets and/or guest badges