How to use efficiently IPSET with CSF Firewall
Tags: linux, firewall, csf, ipset
Published: 2024-03-02 09:30:36

Hello,

This is my first ever post here 😀

In this post we will discuss how to use efficiently IPSET with CSF (ConfigServer Security & Firewall) Firewall. Unfortunately, I will not discuss what CSF is because it's not within the scope, but you can read about it [here](https://configserver.com/configserver-security-and-firewall/).

If you already used CSF or just getting started using it, you might have noticed that the `DENY_IP_LIMIT` and `DENY_TEMP_IP_LIMIT` is relatively small and fills up very fast. CSF advises you to use IPSET if you wish to increase this limit.

What it doesn't tell you clearly is that even if you install IPSET and enable it inside CSF, **you still need to increase** the values of `DENY_IP_LIMIT` and `DENY_TEMP_IP_LIMIT` otherwise it will have no effect. Trust me when I say that such a simple thing caused me quite some headaches...


## What is IPSET?

IPSET is a Linux kernel feature that allows for efficient management of large sets of IP addresses. It's particularly useful for implementing firewalls and access control lists. CSF leverages IPSET for managing IP addresses efficiently.

Diagram:

          +------------+
          |    IPSET   |
          +------------+
                |
        +-------|-------+
        |       |       |
    +-------+ +-------+ +-------+
    | IP    | | IP    | | IP    |
    | Address| | Address| | Address|
    +-------+ +-------+ +-------+

- The "IPSET" box represents the IPSET data structure managed by CSF.
- Each IP address is stored within the IPSET, organized for efficient lookup.
- CSF interacts with IPSET to add, remove, or query IP addresses based on firewall rules and security policies.

## How is IPSET configured in CSF?

By default CSF provides you with following configuration:

```
# The following sets the hashsize for ipset sets, which must be a power of 2.
#
# Note: Increasing this value will consume more memory for all sets
# Default: "1024"
LF_IPSET_HASHSIZE = "1024"

# The following sets the maxelem for ipset sets.
#
# Note: Increasing this value will consume more memory for all sets
# Default: "65536"
LF_IPSET_MAXELEM = "65536"
```

So what does this actually mean for you? The default settings for `LF_IPSET_HASHSIZE` and `LF_IPSET_MAXELEM` in CSF are set conservatively to balance memory usage and performance on a typical system. With this configuration the IPSET can accommodate up to 67,108,864 IP addresses (theoretically 😅).

The configuration settings for `LF_IPSET_HASHSIZE` and `LF_IPSET_MAXELEM` affect the efficiency and capacity of the IPSET data structure within CSF. While it's true that the default configuration allows for a theoretical maximum of over 67 million IP addresses, it's essential to consider limitations such as memory usage and performance.

Generally, increasing `LF_IPSET_MAXELEM` will consume more memory as it allows for storing more IP addresses, while `LF_IPSET_HASHSIZE` primarily affects lookup performance but also has some memory overhead.

**Keep in mind:**

- A larger hash table requires more memory to store IP addresses efficiently. By defaulting to a smaller hash size (`LF_IPSET_HASHSIZE = "1024"`), CSF ensures that it doesn't consume excessive memory resources on systems with limited RAM or where memory usage needs to be carefully managed.
- While a larger hash table can improve lookup performance for IP addresses, it may also introduce overhead in terms of memory access and CPU usage. By keeping the default hash size relatively small, CSF aims to strike a balance between memory consumption and performance impact on the system.
- The default settings are chosen to be compatible with a wide range of systems and use cases. They provide a reasonable starting point that works well for many installations without requiring fine-tuning.
- CSF is designed to be scalable, allowing administrators to adjust settings like `LF_IPSET_HASHSIZE` and `LF_IPSET_MAXELEM` based on their specific requirements and available resources. While the default settings may be conservative, they can be modified to better suit the needs of individual environments.

In summary, the default hash size in CSF is set to a relatively small value to strike a balance between memory usage and performance impact. Administrators can adjust these settings based on their specific requirements, system resources, and performance considerations.

## Increasing IPSET efficiently for performance

In order to store millions of IP addresses efficiently you need to configure the limits accordingly, based on your available resources. As explained earlier, IPSET is mainly about RAM. So with that being said, I will provide example configurations for various amounts of RAM with balanced IP set settings.

These configurations aim to strike a balance between memory usage, performance, and scalability. Keep in mind that these are example configurations, and you may need to adjust them based on your specific requirements and system characteristics.

**System with 2 GB RAM**

- `LF_IPSET_MAXELEM = "65536`
- `LF_IPSET_HASHSIZE = "131072` (Approx. 131K IPs)

**System with 4 GB RAM**

- `LF_IPSET_MAXELEM = "131072"`
- `LF_IPSET_HASHSIZE = "262144"` (~262K IPs)

**System with 6 GB RAM**

- `LF_IPSET_MAXELEM = "196608"`
- `LF_IPSET_HASHSIZE = "393216"` (~393K IPs)

**System with 8 GB RAM**

- `LF_IPSET_MAXELEM = "262144"`
- `LF_IPSET_HASHSIZE = "524288`" (~524K IPs)

**System with 16 GB RAM**

- `LF_IPSET_MAXELEM = "524288"`
- `LF_IPSET_HASHSIZE = "1048576"` (~1M IPs)

**System with 32 GB RAM**

- `LF_IPSET_MAXELEM = "1048576"`
- `LF_IPSET_HASHSIZE = "2097152"` (~2M IPs)

**System with 64 GB RAM**

- `LF_IPSET_MAXELEM = "2097152"`
- `LF_IPSET_HASHSIZE = " 4194304"` (~4M IPs)

**System with 128 GB RAM**

- `LF_IPSET_MAXELEM = "4194304"`
- `LF_IPSET_HASHSIZE = "8388608"` (~8M IPs)

Adjusting `LF_IPSET_HASHSIZE` proportionally higher than `LF_IPSET_MAXELEM` helps maintain efficient lookup times, especially as the number of stored IP addresses increases. These configurations aim to balance memory usage with performance requirements, allowing for optimal operation of CSF IP sets.

You can monitor the current IPSET usage with the following command:

`ipset list -t`

This command will list detailed information about the IP sets, including statistics such as the number of elements and the size of the hash table.

## Potential overhead

When increasing the limits for `LF_IPSET_HASHSIZE` and `LF_IPSET_MAXELEM` in CSF, there are several potential overheads to consider:

- One of the most significant overheads is the increased memory usage. IPSET data structures consume memory, and larger hash tables or higher maximum element limits will require more RAM. This can impact overall system performance, especially on systems with limited memory resources.
- While larger hash tables can improve lookup performance by reducing collisions and improving cache locality, excessively large hash tables may lead to slower lookup times due to increased memory access overhead.
- Allocating more memory for IPSET may lead to resource contention with other processes running on the system. If the system is under heavy load, increased memory usage by IPSET could exacerbate resource contention issues.
- In extreme cases, allocating too much memory for IPSET could potentially lead to system instability, especially if the system runs out of physical memory and starts swapping excessively.

So please keep these in mind and don't start increasing the IPSET limits in CSF on small/budget type VPS.

And that about concludes my first post here. Unfortunately I don't have more time right now to expand this article, but maybe in the coming weeks I will post more useful stuff about CSF 🙂

PS: I really don't like the default editor here. It's too basic and quite bugged.

_Until we meet again!_