Adding servers to CSF cluster

Freddy

Verified User
Joined
Apr 14, 2016
Messages
137
I want to create a CSF cluster so that every IP blockade on each server will become an IP blockade on all servers. I heave read the documentation on this and I've seen the configuration examples for the CLUSTER_SENDTO and CLUSTER_RECVFROM settings. What I don't understand is how unmanageable things become if you have allot of servers and want to add a new one. Do you really need to change the configuration on all servers and add the new IP to the sendto and recvfrom settings? Can this be done in an easier way?
 
you can use one separate server so all servers will send to it and receive from it
I thought so, but I read that the master server does not forward new blockades if another node sends them to avoid loops. So you would need to manually enter all IP's on the master server because that is the only way to send them to other nodes. Is this true?
 
Yes. You can also use a file for it.
Alternatively, it can be set to the full path of a file that will read in one IP per line, e.g.: "/etc/csf/cluster_sendto.txt"
same for the receive from ofcourse.

So if you use a master, you don't need to change the receive_from on all servers, because that will only require the master ip.
And in the master, you can change both the textfiles on server changes and restart csf/lfd and you're done. So not a lot of work, only the first time setup.
 
Yes. You can also use a file for it.

same for the receive from ofcourse.

So if you use a master, you don't need to change the receive_from on all servers, because that will only require the master ip.
And in the master, you can change both the textfiles on server changes and restart csf/lfd and you're done. So not a lot of work, only the first time setup.
But will the master forward all blocks that it receives from the other nodes? If I have 5 nodes from which node 1 is the master, and node 5 sends a new IP block to the master, will the master automatically forward it to nodes 2,3 and 4?
 
But will the master forward all blocks that it receives from the other nodes?

No, it won't. CLUSTER_MASTER in terms of CSF/LFD is a server which is allowed to send configs changes only, see:

The option CLUSTER_MASTER is the IP address of the master node in the cluster
allowed to send CLUSTER_CONFIG changes to servers listed in the local
CLUSTER_SENDTO list. Only cluster members that have CLUSTER_MASTER set to this
IP address will accept CLUSTER_CONFIG changes.


Thus you will need to list all nodes' IPs in CLUSTER_SENDTO and CLUSTER_RECVFROM. But you can use CLUSTER_MASTER to publish updated config file across slaves.

Directadmin supports CSF/LFD natively, but if you want to use CLUSTER mode in CSF/LFD you might use this set of scripts: https://github.com/poralix/directadmin-bfm-csf the version 0.1.7 introduced a support of Cluster mode of CSF/LFD.
 
No, it won't. CLUSTER_MASTER in terms of CSF/LFD is a server which is allowed to send configs changes only, see:

The option CLUSTER_MASTER is the IP address of the master node in the cluster
allowed to send CLUSTER_CONFIG changes to servers listed in the local
CLUSTER_SENDTO list. Only cluster members that have CLUSTER_MASTER set to this
IP address will accept CLUSTER_CONFIG changes.


Thus you will need to list all nodes' IPs in CLUSTER_SENDTO and CLUSTER_RECVFROM. But you can use CLUSTER_MASTER to publish updated config file across slaves.

Directadmin supports CSF/LFD natively, but if you want to use CLUSTER mode in CSF/LFD you might use this set of scripts: https://github.com/poralix/directadmin-bfm-csf the version 0.1.7 introduced a support of Cluster mode of CSF/LFD.
Thanks. This was the answer I was looking for. Since you seem to know more about it I have one more question. I can use a file to provide an IP list to CLUSTER_SENDTO, but what if that file contains the IP of the node itself? Does it hurt? In other words: Can I use one global file with all IP's for all nodes or do I need to create an IP list per node? My goal is to push the file to all servers and never change the csf.conf itself, only restarting csf to allow the new list to be read.
 
but what if that file contains the IP of the node itself?

The IP will be blocked in the firewall on that server too. Let's say you have two nodes:

A: 1.2.3.4
B: 4.3.2.1

The both IPs should be listed either in CLUSTER_SENDTO/CLUSTER_RECVFROM or in /etc/csf/cluster_recvfrom.txt /etc/csf/cluster_sendto.txt

This way an offending IP will be blocked on the both cluster members.

If the server A: 1.2.3.4 finds an attacking IP 2.2.2.2 and triggers a cluster block:

Code:
csf --cdeny 2.2.2.2

The IP will be blocked on servers only listed in CLUSTER_SENDTO,

And if the local IP is not specified, the attacking IP won't be block locally, but only on other members.

I hope I'm clear)

From readme:

In the configuration there are two comma separated lists of IP addresses:

CLUSTER_SENDTO = ""
CLUSTER_RECVFROM = ""

Note: Do not use spaces in these lists

If you want all members of the lfd cluster to send block notifications to each
other then both settings should be them same. You also need to enable
CLUSTER_BLOCK (enabled by default) for lfd to automatically send blocks to all
members in CLUSTER_SENDTO.

However, you can also set up a cluster such that some members only provide
notifications to others and do not accept blocks from others. For example, you
may have a cluster of servers that includes one that hosts a support desk that
you do not want to block clients from accessing. In such an example you might
want to exclude the support desk server from the CLUSTER_SENDTO list, but
include it in the CLUSTER_RECVFROM list.

Can I use one global file with all IP's for all nodes

Yes you can. And you would rather do it
 
I was in the assumption that temporary IP bans which are added through the web-interface of CSF are automatically synced across all nodes, but this doesn't seem to be working. I need to specifically call the csf -ctd to add the IP to all nodes. Is this really the only way?
 
will the master automatically forward it to nodes 2,3 and 4?
Yes. But I was talking about master in terms as "the main server to which all reports are send and which reports to all others". Since you wanted to use a server as master server for the reports and used the term master yourself.
Ofcourse not the cluster_master, because that is only about configs as @zEitEr correctly wrote and is mentioned in the config also.
Just to have this clear for anybody reading this.

Can I use one global file with all IP's for all nodes or do I need to create an IP list per node?
That depends on what you want to do. If you want to use 1 "master" which receives from all nodes and send to all nodes, then at this "master" you need the ip's for -all- nodes both in the CLUSTER_RECVFROM and CLUSTER_SENDTO files.

All other servers only need to have 1 ip address in each file, which is the ip address of the "master" you want to use in the CLUSTER_RECVFROM and 1 ip address from the same master to send reports in the CLUSTER_SENDTO file.
Again... not the cluster_master setting ofcourse.

I need to specifically call the csf -ctd to add the IP to all nodes. Is this really the only way?
It can be done via console or automatically on bruteforcing by using a script in the custom scripts directory.
I don't know if something like that can also can be done via some post script when using the plugin, maybe @zEitEr knows.
 
Last edited:
I need to specifically call the csf -ctd to add the IP to all nodes. Is this really the only way?

You might use scripts/custom/all_pre.sh under directadmin. The CSF plugin defines the following variables:

Bash:
ip=21.21.21.21
action=qallow
command=/CMD_PLUGINS_ADMIN/csf/index.raw

  • ip= - IP address used in the action from CSF interface/plugin in DA
  • action= - action from CSF interface/plugin in DA, where qallow - quick allow, qdeny - quick deny, etc.
  • command=/CMD_PLUGINS_ADMIN/csf/index.raw - the core identifier showing that we deal with the CSF plugin

You can use the mentioned hook in DirectAdmin with any programming language: bash, perl, PHP, etc and trigger a custom action with CLUSTER flags of CSF.

The all_pre.sh script is under a risk to be deprecated, but while it's in a game, you are welcome to use it.

If you don't have programming skills, you might ask somebody here to help you. I'm available for this job under commercial terms.
 
I have been testing my cluster with 3 servers now:
10.0.0.2 (CLUSTER_SENDTO = "10.0.0.3, 10.0.0.4", CLUSTER_RECVFROM = "10.0.0.3, 10.0.0.4", CLUSTER_MASTER = "")
10.0.0.3 (CLUSTER_SENDTO = "10.0.0.2", CLUSTER_RECVFROM = "10.0.0.2", CLUSTER_MASTER = "10.0.0.2")
10.0.0.4 (CLUSTER_SENDTO = "10.0.0.2", CLUSTER_RECVFROM = "10.0.0.2", CLUSTER_MASTER = "10.0.0.2")

Nodes 3 and 4 only send their bans to node 2. Node 2 should store bans and forward them to all other servers, so to node 3 and 4 in this case.

That depends on what you want to do. If you want to use 1 "master" which receives from all nodes and send to all nodes, then at this "master" you need the ip's for -all- nodes both in the CLUSTER_RECVFROM and CLUSTER_SENDTO files.

All other servers only need to have 1 ip address in each file, which is the ip address of the "master" you want to use in the CLUSTER_RECVFROM and 1 ip address from the same master to send reports in the CLUSTER_SENDTO file.
As you can read above, I configured it this way but it does not seem to work like you said. When I manually execute a cluster temp ban command (csf -ctd) on node 3 then the master node 2 receives it but does not forward it. What am I missing?

Another thing to mention is that my deny file holds bans from both BFM as well as from LFD itself. Bans from LFD are shared among the cluster, but bans from BFM are not.

For example, logs from node 2:
Code:
<IP-1> # lfd: (smtpauth) Failed SMTP AUTH login from <IP-1>: 5 in the last 3600 secs - Tue Apr  8 02:49:32 2025
<IP-2> # BFM: wordpress2=271 (-) - Tue Apr  8 03:00:40 2025
<IP-3> # BFM: dovecot1=30 (-) - Tue Apr  8 03:05:42 2025
<IP-4> # lfd: (smtpauth) Failed SMTP AUTH login from <IP-4> (-): 5 in the last 3600 secs - Tue Apr  8 03:05:53 2025
<IP-5> # BFM: dovecot1=30 (-) - Tue Apr  8 03:08:40 2025
Both LFD bans are now banned on all nodes, but the BFM bans are only on the source node. I guess DirectAdmin is by default not cluster-aware so nothing is shared. I was hoping CSF would do this automatically but it seems every ban needs to be send by scripting. Or am I missing something?
 
Node 2 should store bans and forward them to all other servers,
Yes but keep in mind that you don't need the CLUSTER_MASTER setting for this. That is only for configs. However if you want to send changed configs to the other nodes too, then ofcourse you do need it.
But in fact it should work as you say.

master node 2 receives it but does not forward it. What am I missing?
Did you create and configured the CLUSTER_KEY correctly on all servers? And also the same CLUSTER_PORT on all servers?
I presume you used the 10 ip range as example. If not, then you also have to configure the CLUSTER_NAT setting.
I also presume you have the CLUSTER_BLOCK set to 1 and same for CLUSTER_CONFIG since you're using the CLUSTER_MASTER.

Something there must be wrong somewhere or maybe another firewall (datacenter?) blocking the csf port from the 2 node or something because I have it working this way. And both bans and tempbans are shared.

As for the BFM and LFD story, that is most likely the way how DA configures things. It uses both BFM and LFD. If you do not want to use BFM for blocking, then you have to take care the BFM blocks are done bij LFD too.

You can use the scripts that @zEitEr has created, you can find them here:
 
Did you create and configured the CLUSTER_KEY correctly on all servers?
Yes, because bans are shared. But only when send directly from the master node. Not when they originate from other nodes and forwarded by the master node.

And also the same CLUSTER_PORT on all servers?
Yes.

I presume you used the 10 ip range as example. If not, then you also have to configure the CLUSTER_NAT setting.
No, the 10 range is my internal network. No NAT required. CSF itself says this about CLUSTER_NAT:
CLUSTER_NAT that should be used if the IP address of the server does not appear in ip/ifconfig
All the IP ranges I use are visible in ifconfig and communication works fine. csf --cping receives an answer from all nodes.

I also presume you have the CLUSTER_BLOCK set to 1 and same for CLUSTER_CONFIG since you're using the CLUSTER_MASTER.
That is correct.

Something there must be wrong somewhere or maybe another firewall (datacenter?) blocking the csf port from the 2 node or something because I have it working this way. And both bans and tempbans are shared.
I'm sorry, but communication works. Bans are already shared, like I said. And cping is working. I really doubt forwarding works like you tell it. I can't find any source for your claims in the documentation. The only way to distribute bans seems to be by sending them from each node and receiving them on each node. And that means that there is also no easy way to configure a huge list of servers. My best bet now is to create a txt file noting each IP and distribute the file to all nodes with the csf --cfile command, then restart all nodes with the csf --crestart command. If each node is configured to read that txt file for the CLUSTER_SENDTO and the CLUSTER_RECVFROM settings than they all talk to each other.

As for the BFM and LFD story, that is most likely the way how DA configures things.
Maybe I can start a Feature Request topic for this.
 
I really doubt forwarding works like you tell it.
I have only 2 servers and that is working. I had 3 before and working but shared another way.
I've been reading the readme.txt again now also next to the csf.conf and it looks like the cluster only works when all servers have the receive and send config of all others. The csf.conf documentation is a but confusing about that.
The cluster_master is only for configs, but this, and the text "where a group of servers can share blocks" gives the impression that you can also do this sharing from 1 server. Unfortunately this seems only applicable for the config.

So on every server you want to share, you do have to use the ip's from the other servers in receive and send. They do send to each other, but they do not forward.

My best bet now is to create a txt file noting each IP and distribute the file to all nodes with the csf --cfile command
Yes either that or put the ip's in the csf.conf of the "master" and restart the master which should update all configs on the others.
You should be able to do that with a textfile, but I wonder if that will be shared (created) on the other nodes as it says the config is shared. So I'm curious as to what will happen.

Please keep us updated on the results.
 
I have only 2 servers and that is working.
On 2 servers there is not allot to forward. ;)

So on every server you want to share, you do have to use the ip's from the other servers in receive and send. They do send to each other, but they do not forward.
That seems to be the conclusion for my main question. So there is no easy way to add servers without at least changing the configuration on all servers.

Yes either that or put the ip's in the csf.conf of the "master" and restart the master which should update all configs on the others.
No, this is not how that works. The config is never shared because that would also mean all the other nodes receive the exact same value for CLUSTER_MASTER. The master is able to share configuration options through the csf --cconfig command, but only for a single option per command. And never automatically, unless you script your way to automation. The --cconfig parameter could be an option to share the IP list for CLUSTER_SENDTO and CLUSTER_RECVFROM but my case with the txt file would probably be easier.
 
So there is no easy way to add servers without at least changing the configuration on all servers.
I'm wondering if it can be more easily done via a script. I use Abuseipdb and all blocks, also received from other servers, were send to Abuseipdb.
However that would take some custom scripting.

No, this is not how that works.
Oeps yes, indeed. But seems your partly correct. The csf --config is not changed automatically indeed. Still not quite clear to me if the --cconfig will change the complete config or only things changed the the master config. And if so, how does it detect that options in the receiving server were different before and should be kept that way.
However, according to the Readme it's not only for a single option per command. The readme states --cconfig can be used if multiple changes are required. And a --cconfigr is also to be done to make changes immediatly.

Using a .txt file is probably easier yes. I presume you will update the .txt on the servers via an rsync cron or something like that? Because I'm not sure if --cfile will also support those non-csf files and it --cfile is also a manual action just like the --cconfig command.

On 2 servers there is not allot to forward. ;)
Yes but as said, I had 3 but shared it another way. ;)
 
I presume you will update the .txt on the servers via an rsync cron or something like that? Because I'm not sure if --cfile will also support those non-csf files and it --cfile is also a manual action just like the --cconfig command.
--cfile works with any file inside the /etc/csf folder. You do have to specify the full path, so something like csf --cfile /etc/csf/myservers.txt. I already have it working with my txt file. I can now add a server from the master server and push the config to all nodes.
 
Ah great! Is a send of a --crestart also needed to restart the node csf/lfd so they will re-read the new .txt file or is a restart not needed?
Good question! I just checked this and a restart is not required. I can edit the file and do a cping, and CSF will use the new txt file right away! After I used csf --cfile to distribute the new txt file to other nodes they also do not require a restart. Cping works instantly on the other nodes. I didn't expect that so this is a nice find. Using a file for the IP nodes was already a good choice and this makes it even better.

[edit] I might have jumped conclusions. After adding several new servers I conclude that a restart of all nodes is probably required to make it work. I don't know why it worked with the test I did earlier, but I now see different results. I now do a cluster restart with csf --crestart after sending the new node txt file, and I do a master restart after the cluster restart with csf --restartall because otherwise the new node cannot cping to the master. I don't know why the master needs to restart separately. Maybe a cluster restart does not include the master himself, even though the IP is mentioned and confirmed.
 
Last edited:
Back
Top