A rest application to update firewalld rules on a linux server

Mentioned in Awesome Go Go Report Card codecov version

Firewalld-rest

A REST application to dynamically update firewalld rules on a linux server.

Firewalld is a firewall management tool for Linux operating systems.

Purpose

If you have seen this message when you login to your linux server:

There were 534 failed login attempts since the last successful login.

Then this idea is for you.

The simple idea behind this is to have a completely isolated system, a system running Firewalld that does not permit SSH access to any IP address by default so there are no brute-force attacks. The only way to access the system is by communicating with a REST application running on the server through a valid request containing your public IP address.

The REST application validates your request (it checks for a valid JWT, covered later), and if the request is valid, it will add your IP to the firewalld rule for the public zone for SSH, which gives only your IP SSH access to the machine.

Once you are done using the machine, you can remove your IP interacting with the same REST application, and it changes rules in firewalld, shutting off SSH access and isolating the system again.

Comparison with fail2ban

This repo takes a proactive approach rather than a reactive approach taken by fail2ban. fail2ban dynamically alters the firewall rules to ban addresses that have unsuccessfully attempted to login a certain number of times. It is reactive - it allows people to try and login to the server, but bans those who are unsuccessful in doing so after a certain number of times. It is like appointing a guard (aka firewall) outside a locked building who checks for suspicious activity and the guard is told by fail2ban to ban anyone who tries to open the lock unsuccessfully many times.

Firewalld-rest is more of a proactive approach. Let me explain.

Proactive approach

By using the approach presented in this repo, you still add a guard (aka firewall) like you did for fail2ban in front of your locked building (aka the server). But there are 2 main differences here:

  1. This guard is told to not let anyone come near the building by default, so that no one is ever close enough to the lock to try their keys. (This means that the default firewall rules are set up by default in such a way so that no one can even try to SSH to the server).
  2. You can talk to the guard (aka firewall) using this repo, and convince the guard to allow you near the building, provided you possess a certain key (an RS256 type, covered later). (This means that using the REST interface provided by this repo, you proactively alter firewall rules to allow ONLY your IP to try and login to the server)

Note: Once you are allowed through by the firewall, you still need to have the key to login to the server.

It is proactive - You proactively talk to the REST interface and alter the firewall rules to allow your IP to try and login.

TL;DR

fail2ban firewalld-rest
dynamically alters firewall rules to ban IP addresses that have unsuccessfully attempted to login to server a certain number of times. provides REST interface to manually alter firewall rules to allow ONLY your IP to try and login to server. No IP apart from yours can even try to login to server.
Reactive - it alters firewall rules after unsuccessfully attempts Proactive - you alter firewall rules before trying to login to server

Note: I am not saying one approach is better than the other. They are just different approaches to the same problem.

Table of Contents

1. Pre-requisites

This repo assumes you have:

  1. A linux server with firewalld installed.
  2. root access to the server. (without root access, the application will not be able to run the firewall-cmd commands needed to add the rule for SSH access)
  3. Some way of exposing the application externally (there are examples in this repo on how to use Kubernetes to expose the service)

2. About the application

2.1 Firewall-cmd

Firewall-cmd is the command line client of the firewalld daemon. Through this, the REST application adds the rule specific to the IP address sent in the request.

The syntax of adding a rule for an IP address is: firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="10.xx.xx.xx/32" port protocol="tcp" port="22" accept'

Once the rule for the IP address has been added, the IP address is stored in a database (covered next). The database is just to keep track of all IPs that have rules created for them.

2.2 Database

The database for the application stores the list of IP addresses that have rules created for them which allow SSH access for those IPs. Once you interact with the REST application and the application creates a firewalld rule specific to your IP address, then your IP address is stored in the database. It is important that the database is maintained during server restarts, otherwise there may be discrepancy between the IP addresses having firewalld rules and IP addresses stored in the database.

Note: Having an IP in the database does not mean that IP address will be given SSH access. The database is just a way to reference all the IPs with rules created in firewalld.

The application uses a file type database for now. The architecture of the code allows easy integration of any other type of databases. The interface in db.go is what is required to be fulfilled to introduce a new type of database.

2.3 Authorization

The application uses RS256 type algorithm to verify the incoming requests.

RS256 (RSA Signature with SHA-256) is an asymmetric algorithm, and it uses a public/private key pair: the identity provider has a private (secret) key used to generate the signature, and the consumer of the JWT gets a public key to validate the signature.

The public certificate is in this file publicCert.go, which is something that will have to be changed before you can use it. (more information on how to create a new one later).

2.4 Tests

The tests can be run using make test. The emphasis has been given to testing the handler functions and making sure that IPs get added and removed successfully from the database. I still have to figure out how to actually automate the tests for the firewalld rules (contributions are welcome!)

3. How to install and use on server

3.1 Generate JWT

Update the file publicCert.go with your own public cert for which you have the private key.

If you want to create a new set, see the section on generating your own public/private key. Once you have your own public and private key pair, then after updating the file above, you can go to jwt.io and generate a valid JWT using RS256 algorithm (the payload doesn't matter). You will be using that JWT to make calls to the REST application, so keep the JWT safe.

3.2 Build the application

Run the command:

make build-linux DB_PATH=/dir/to/db/

It will create a binary under the build directory, called firewalld-rest. The DB_PATH=/dir/to/keep/db statement sets the path where the .db file will be saved on the server. It should be saved in a protected location such that it is not accidentally deleted on server restart or by any other user. A good place for it could be the same directory where you will copy the binary over to (in the next step). That way you will not forget where it is.

If DB_PATH variable is not set, the db file will be created by default under /. (This happens because the binary is run by systemd. If we manually ran the binary file on the server, the db file would be created in the same directory.)

Once the binary is built, it should contain everything required to run the application on a linux based server.

3.3 Copy binary file over to server

scp build/firewalld-rest root@<server>:/root/rest

Note: if you want to change the directory where you want to keep the binary, then make sure you edit the firewalld-rest.service file, as the linux systemd service definition example in this repo expects the location of the binary to be /root/rest.

3.4 Remove SSH from public firewalld zone

This is to remove SSH access from the public zone, which will cease SSH access from everywhere.

SSH into the server, and run the following command:

firewall-cmd --zone=public --remove-service=ssh --permanent

then reload (since we are using --permanent):

firewall-cmd --reload

This removes ssh access for everyone. This is where the application will come into play, and we enable access based on IP.

Confirmation for the step:

firewall-cmd --zone=public --list-all

Notice the ssh service will not be listed in public zone anymore.

Also try SSH access into the server from another terminal. It should reject the attempt.

3.5 Expose the REST application

The REST application can be exposed in a number of different ways, I have 2 examples on how it can be exposed:

  1. Using a NodePort kubernetes service (link)
  2. Using ingress along with a kubernetes service (link)

3.5.1 Single node cluster

For a single-node cluster, see the kubernetes service example here. The important thing to note is that we manually add the Endpoints resource for the service, which points to our node's private IP address and port 8080.

Once deployed, your service might look like this:

kubernetes get svc

external-rest | NodePort | 10.xx.xx.xx | 169.xx.xx.xx | 8080:31519/TCP

Now, you can interact with the application on:

169.xx.xx.xx:31519/m1/

Note: Since there's only 1 node in the cluster, you will only ever use /m1. For more than 1 node, see the next section.

3.5.2 Multi-node cluster

For a multi-node cluster, an ingress resource would be highly beneficial.

The first step would be to create the kubernetes service in each individual node, using the example here. The important thing to note is that we manually add the Endpoints resource for the service, which points to our node's private IP address and port 8080.

The second step is the ingress resource. It redirects different routes to different nodes in the cluster. For example, in the ingress file above,

A request to /m1 will be redirected to the first node, a request to /m2 will be redirected to the second node, and so on. This will let you control each node's individual SSH access through a single endpoint.

3.6 Configure linux systemd service

See this for an example of a linux systemd service.

The .service file should be placed under etc/systemd/system directory.

Note: This service assumes your binary is at /root/rest/firewalld-rest. You can change that in the file above.

3.7 Start and enable systemd service.

Start

systemctl start firewalld-rest

Logs

You can see the logs for the service using:

journalctl -r

Enable

systemctl enable firewalld-rest

3.8 IP JSON

This is how the IP JSON looks like, so that you know how you have to pass your IP and domain to the application:

type IP struct {
	IP     string `json:"ip"`
	Domain string `json:"domain"`
}

3.9 Interacting with the REST application

3.9.1 Index page

route{
    "Index Page",
    "GET",
    "/",
}
Sample query
curl --location --request GET '<SERVER_IP>:8080/m1' \
--header 'Authorization: Bearer <jwt>'

3.9.2 Show all IPs

route{
    "Show all IPs present",
    "GET",
    "/ip",
}
Sample query
curl --location --request GET '<SERVER_IP>:8080/m1/ip' \
--header 'Authorization: Bearer <jwt>'

3.9.3 Add new IP

route{
    "Add New IP",
    "POST",
    "/ip",
}
Sample query
curl --location --request POST '<SERVER_IP>:8080/m1/ip' \
--header 'Authorization: Bearer <jwt>' \
--header 'Content-Type: application/json' \
--data-raw '{"ip":"10.xx.xx.xx","domain":"example.com"}'

3.9.4 Show if IP is present

route{
    "Show if particular IP is present",
    "GET",
    "/ip/{ip}",
}
Sample query
curl --location --request GET '<SERVER_IP>:8080/m1/ip/10.xx.xx.xx' \
--header 'Authorization: Bearer <jwt>'

3.9.5 Delete IP

route{
    "Delete IP",
    "DELETE",
    "/ip/{ip}",
}
Sample query
curl --location --request DELETE '<SERVER_IP>:8080/m1/ip/10.xx.xx.xx' \
--header 'Authorization: Bearer <jwt>'

4. Helpful tips/links

5. Commands for generating public/private key

openssl genrsa -key private-key-sc.pem
openssl req -new -x509 -key private-key-sc.pem -out public.cert

6. Possible enhancements

  • Rate limiting the number of requests that can be made to the application
Similar Resources

BadActor.org An in-memory application driven jailer written in Go

BadActor.org An in-memory application driven jailer written in Go

BadActor BadActor is an in-memory, application driven jailer built in the spirit of fail2ban. A middleware with the primary goal to increase the expen

Dec 16, 2022

Open Source Web Application Firewall

Open Source Web Application Firewall

DEPRECATED This repository started as a good idea but I didn't have enough time or desire to work on it. So, it's left here for historical / education

Nov 24, 2022

Sqreen's Application Security Management for the Go language

Sqreen's Application Security Management for the Go language

Sqreen's Application Security Management for Go After performance monitoring (APM), error and log monitoring it’s time to add a security component int

Dec 27, 2022

A web-based testing platform for WAF (Web Application Firewall)'s correctness

WAFLab 🐾 WAFLab is a web-based platform for testing WAFs. Live Demo https://waflab.org/ Architecture WAFLab contains 2 parts: Name Description Langua

Oct 25, 2022

A vulnerable graphQL application, for testing purposes

Vulnerable-GoQL Vulnerable-GoQL is an web API which implements main security breach.

Jul 31, 2021

Coraza WAF is a golang modsecurity compatible web application firewall library

Coraza WAF is a golang modsecurity compatible web application firewall library

Coraza Web Application Firewall, this project is a Golang port of ModSecurity with the goal to become the first enterprise-grade Open Source Web Application Firewall, flexible and powerful enough to serve as the baseline for many projects.

Jan 9, 2023

2FA (Two-Factor Authentication) application for CLI terminal with support to import/export andOTP files.

2FA (Two-Factor Authentication) application for CLI terminal with support to import/export andOTP files.

zauth zauth is a 2FA (Two-Factor Authentication) application for terminal written in Go. Features Supports both TOTP and HOTP codes. Add new entries d

Nov 27, 2022

Example mini project golang scanner application

Example mini project golang scanner application

Golang Scanner Contoh pembuatan aplikasi Java menggunakan BlueJ cek disini, tetapi berikut ini adalah versi rebuild dari Java ke Golang, dengan menggu

Nov 19, 2022
Comments
  • proposed feedback comments

    proposed feedback comments

    Feedback comments being targeted:

    1. Removing local db, all IPs will be fetched directly from the firewall rules.
    2. Validation of IPv4 address before adding

    Update

    I am thinking whether removing the db is a good idea or not, since the db helps me keep the domain along with the IP address. Removing db will just give me a list of IP addresses, without having any other metadata about them.

mesh-kridik is an open-source security scanner that performs various security checks on a Kubernetes cluster with istio service mesh and is leveraged by OPA (Open Policy Agent) to enforce security rules.
mesh-kridik is an open-source security scanner that performs various security checks on a Kubernetes cluster with istio service mesh and is leveraged by OPA (Open Policy Agent) to enforce security rules.

mesh-kridik Enhance your Kubernetes service mesh security !! mesh-kridik is an open-source security scanner that performs various security checks on a

Dec 14, 2022
Update-java-ca-certificates - Small utility to convert the system trust store to a system Java KeyStore

update-java-ca-certificates This small utility takes care of creating a system-w

Dec 28, 2022
Automatic Linux privesc via exploitation of low-hanging fruit
Automatic Linux privesc via exploitation of low-hanging fruit

Traitor Automatically exploit low-hanging fruit to pop a root shell. Linux privilege escalation made easy! Traitor packages up a bunch of methods to e

Jan 1, 2023
Tracee: Linux Runtime Security and Forensics using eBPF
Tracee: Linux Runtime Security and Forensics using eBPF

Tracee is a Runtime Security and forensics tool for Linux. It is using Linux eBPF technology to trace your system and applications at runtime, and analyze collected events to detect suspicious behavioral patterns.

Jan 5, 2023
Agent-less vulnerability scanner for Linux, FreeBSD, Container, WordPress, Programming language libraries, Network devices
Agent-less vulnerability scanner for Linux, FreeBSD, Container, WordPress, Programming language libraries, Network devices

Vuls: VULnerability Scanner Vulnerability scanner for Linux/FreeBSD, agent-less, written in Go. We have a slack team. Join slack team Twitter: @vuls_e

Jan 9, 2023
Jan 6, 2023
golang users friendly linux hacking library.
golang users friendly linux hacking library.

go-cheat users friendly linux hacking library

Nov 9, 2022
Find vulnerable versions of Log4j on Linux

log4jtool Find vulnerable versions of Log4j on Linux This tool does not change a

Jan 14, 2022
Golang Port Knocking for Linux + Windows

Vishnu(The Hidden Backdoor) RS{JOIN_REDTEAM} Taken from the Trimurit, the triple deity of supreme divinity. Vishnu is known as "The Preserver". This p

Nov 9, 2022
Collects REST Api calls for log4j reports

log4j-collector This is a simple log4j collector that will collect logs from a H

Dec 20, 2021