|
| 1 | +--- |
| 2 | +id: log_centralization |
| 3 | +title: Log Centralization |
| 4 | +sidebar_position: 10 |
| 5 | +--- |
| 6 | + |
| 7 | +## Introduction |
| 8 | + |
| 9 | +If you expose services on the internet from multiple servers, setting up crowdsec on all of them might make the overall setup more complex. |
| 10 | + |
| 11 | +To simplify things, you can use a central server to receive all your logs and only run a single instance of crowdsec on this server. |
| 12 | + |
| 13 | +In this guide, our goal is to centralize two types of logs: |
| 14 | + - Nginx logs |
| 15 | + - SSH auth logs |
| 16 | + |
| 17 | +We'll configure nginx to forward the access logs to our central rsyslog server.<br/> |
| 18 | +We'll configure a local rsyslog for the auth logs on each web server and forward them to our central server. |
| 19 | + |
| 20 | +On the central server, a rsyslog server will receive those logs and write them into files.<br/> |
| 21 | +The Security Engine will analyze those logs on this same server to detect malicious behaviours.<br/> |
| 22 | +Finally, we will have a Firewall Remediation Component running on each web server to block the malicious IPs. |
| 23 | + |
| 24 | + |
| 25 | +Our infrastructure will look like this: |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +Before diving into the setup, a few key points: |
| 30 | + - If you have a firewall, you will need to allow communication on 514/UDP (Syslog) and 8080/TCP (crowdsec LAPI) from the web servers to the central server |
| 31 | + - By default, rsyslog is a clear-text protocol. If all the machines interact over LAN, this is probably not an issue, but if they communicate over the internet, you will probably want to set up TLS on the syslog server. |
| 32 | + |
| 33 | +## Rsyslog Server Setup |
| 34 | + |
| 35 | +Let's start by setting up our central rsyslog. |
| 36 | + |
| 37 | +If rsyslog is not installed, you can install it with `apt install rsyslog` (assuming a debian-like distribution). |
| 38 | + |
| 39 | +The first step is to configure rsyslog with a UDP listener and a template to write the received logs to disk. |
| 40 | + |
| 41 | +Create the file `/etc/rsyslog.d/10_remote.conf` with the following content: |
| 42 | +``` |
| 43 | +# Load the UDP receiver |
| 44 | +module(load="imudp") |
| 45 | +input(type="imudp" port="514") |
| 46 | +
|
| 47 | +# Create a template for the logs |
| 48 | +template(name="NginxLogs" type="string" string="/var/log/remote-logs/nginx/%HOSTNAME%.log") |
| 49 | +template(name="AuthLogs" type="string" string="/var/log/remote-logs/auth/%HOSTNAME%.log") |
| 50 | +
|
| 51 | +# Rsyslog will write both access logs and error logs to the same file |
| 52 | +# You can split them by using a custom program name on the nginx side |
| 53 | +if ($inputname == 'imudp' and $programname == 'nginx') then ?NginxLogs |
| 54 | +& stop |
| 55 | +
|
| 56 | +# Write SSH logs to auth.log |
| 57 | +if ($inputname == 'imudp' and $programname == 'sshd') then ?AuthLogs |
| 58 | +& stop |
| 59 | +
|
| 60 | +# Drop everything else; we are not interested in them |
| 61 | +if ($inputname == 'imudp') then stop |
| 62 | +``` |
| 63 | + |
| 64 | +Then, we need to create the `/var/log/remote-logs/` to store logs: |
| 65 | +```bash |
| 66 | +$ sudo mkdir /var/log/remote-logs/ && sudo chown syslog:syslog /var/log/remote-logs/ |
| 67 | +``` |
| 68 | + |
| 69 | +You will also need to edit `/etc/rsyslog.conf` to make sure `$RepeatedMsgReduction` is set to `off` (some distributions set it to `on` by default, but this is rarely recommended, especially when consuming potentially a high volume of logs) |
| 70 | + |
| 71 | +Finally, restart rsyslog to use the new configuration: |
| 72 | +```bash |
| 73 | +systemctl restart rsyslog |
| 74 | +``` |
| 75 | + |
| 76 | +We will also set up Logrotate to avoid filling our disk with the logs. Create a file `/etc/logrotate.d/remote-logs` with the following content: |
| 77 | +``` |
| 78 | +/var/log/remote-logs/*/*.log { |
| 79 | + daily |
| 80 | + rotate 7 |
| 81 | + compress |
| 82 | + missingok |
| 83 | + notifempty |
| 84 | + create 0640 syslog adm |
| 85 | + sharedscripts |
| 86 | + postrotate |
| 87 | + /bin/systemctl reload rsyslog.service > /dev/null 2>&1 || true |
| 88 | + endscript |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +This configuration will keep 7 days of compressed logs. |
| 93 | + |
| 94 | +## Rsyslog Client Setup |
| 95 | + |
| 96 | +### Nginx logs |
| 97 | + |
| 98 | +Update your nginx configuration to send the access and error logs over syslog to our central server: |
| 99 | +``` |
| 100 | +access_log syslog:server=<central-server-ip>; |
| 101 | +error_log syslog:server=<central-server-ip>; |
| 102 | +``` |
| 103 | + |
| 104 | +As nginx supports multiple `access_log` and `error_log` directives, you can keep the existing directives to keep a local copy of the logs. |
| 105 | + |
| 106 | +### Auth logs |
| 107 | + |
| 108 | +Create a file `/etc/rsyslog.d/99-auth-forward.conf` with the following content: |
| 109 | +``` |
| 110 | +auth,authpriv.* @<central-server-ip>:514 |
| 111 | +``` |
| 112 | + |
| 113 | +Restart the rsyslog client: |
| 114 | +```bash |
| 115 | +$ systemctl restart rsyslog |
| 116 | +``` |
| 117 | + |
| 118 | +## CrowdSec Setup |
| 119 | + |
| 120 | +### Central Server |
| 121 | + |
| 122 | +Back on the central server, let's install crowdsec. |
| 123 | + |
| 124 | +First, we need to add the crowdsec repository: |
| 125 | +```bash |
| 126 | +$ curl https://install.crowdsec.net | sudo bash |
| 127 | +``` |
| 128 | + |
| 129 | +Next, we install crowdsec: |
| 130 | +```bash |
| 131 | +$ sudo apt install crowdsec |
| 132 | +``` |
| 133 | + |
| 134 | +CrowdSec will automatically detect we are running on a Linux server and install the base Linux collection. |
| 135 | + |
| 136 | +But because our logs are not in a standard location, we need to configure the acquisition to tell crowdsec where our logs are. |
| 137 | + |
| 138 | +Create a file in `/etc/crowdsec/acquis.d/nginx.yaml` with the following content: |
| 139 | +``` |
| 140 | +filenames: |
| 141 | + - /var/log/remote-logs/nginx/*.log |
| 142 | +labels: |
| 143 | + type: syslog |
| 144 | +``` |
| 145 | + |
| 146 | +Repeat for auth logs, create a file `/etc/crowdsec/acquis.d/ssh.yaml` with the following content: |
| 147 | +``` |
| 148 | +filenames: |
| 149 | + - /var/log/remote-logs/auth/*.log |
| 150 | +labels: |
| 151 | + type: syslog |
| 152 | +``` |
| 153 | + |
| 154 | +Note that we are setting the type label to `syslog`, instructing crowdsec to use the `syslog` parser to extract the actual type from the log itself. |
| 155 | + |
| 156 | +Then, we need to install the nginx collection for crowdsec to be able to detect attacks: |
| 157 | +```bash |
| 158 | +$ sudo cscli collections install crowdsecurity/nginx |
| 159 | +``` |
| 160 | + |
| 161 | +Lastly, we will also need to make crowdsec on all interfaces to make sure our web servers can contact LAPI.<br/> |
| 162 | +Edit the file `/etc/crowdsec/config.yaml`, and set `api.server.listen_uri` to `0.0.0.0:8080`: |
| 163 | +```yaml |
| 164 | +api: |
| 165 | + server: |
| 166 | + listen_uri: 0.0.0.0:8080 |
| 167 | +``` |
| 168 | +
|
| 169 | +Finally, restart crowdsec: |
| 170 | +```bash |
| 171 | +$ sudo systemctl restart crowdsec |
| 172 | +``` |
| 173 | + |
| 174 | +### Remediation components setup |
| 175 | + |
| 176 | +CrowdSec, by itself, will only detect bad behaviors and make decisions about IPs; it will not block them. |
| 177 | + |
| 178 | +To block an IP, you need to install a [remediation component](/unversioned/bouncers/intro.md). |
| 179 | + |
| 180 | +For this guide, we'll be using the [firewall remediation component](/unversioned/bouncers/firewall.mdx) that will add local firewall rules to block malicious IPs. |
| 181 | + |
| 182 | +On your web servers, add the crowdsec repository: |
| 183 | +```bash |
| 184 | +$ curl https://install.crowdsec.net/ | bash |
| 185 | +``` |
| 186 | + |
| 187 | +Then, install the firewall remediation component: |
| 188 | +```bash |
| 189 | +$ sudo apt install crowdsec-firewall-bouncer-nftables |
| 190 | +``` |
| 191 | + |
| 192 | +We now need to create API keys for both our remediation components. |
| 193 | +On the central server, run the commands: |
| 194 | +```bash |
| 195 | +$ sudo cscli bouncers add fw-bouncer-web-1 |
| 196 | +API key for 'fw-bouncer-web-1': |
| 197 | + |
| 198 | + v3G2V//B4IAEFUkON3zWq5yz331UGZDQlQercn3n5T8 |
| 199 | + |
| 200 | +Please keep this key since you will not be able to retrieve it! |
| 201 | +$ sudo cscli bouncers add fw-bouncer-web-2 |
| 202 | +API key for 'fw-bouncer-web-2': |
| 203 | + |
| 204 | + Nda9MreJsUBt/EEmz3TI0Jr6p1a9U2XSx5CEeVfkNRw |
| 205 | + |
| 206 | +Please keep this key since you will not be able to retrieve it! |
| 207 | +``` |
| 208 | + |
| 209 | +Now, on each web server, edit the file `/etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml` and update the `api_url` options with the IP on the central server, and paste the API key in `api_key`: |
| 210 | + |
| 211 | +```yaml |
| 212 | +api_url: http://<central-server-ip>:8080/ |
| 213 | +api_key: <API_KEY> |
| 214 | +``` |
| 215 | +
|
| 216 | +Finally, restart the remediation component: |
| 217 | +```bash |
| 218 | +$ sudo systemctl restart crowdsec-firewall-bouncer |
| 219 | +``` |
| 220 | + |
| 221 | +## Test |
| 222 | + |
| 223 | +Now that everything is setup, it's time to test ! |
| 224 | + |
| 225 | +We'll scan one of our web servers, and because both of them are querying the same crowdsec instance if one detects the attack, the other server will also block the attacker. |
| 226 | + |
| 227 | +:::info |
| 228 | + |
| 229 | +Replace the placeholders with the actual IP of your servers |
| 230 | + |
| 231 | +::: |
| 232 | + |
| 233 | +```bash |
| 234 | +$ nikto -h <server_1> |
| 235 | +``` |
| 236 | + |
| 237 | +After the scan is done, try to access the two servers with curl: |
| 238 | + |
| 239 | +```bash |
| 240 | +$ curl --connect-timeout 2 <server_1> |
| 241 | +curl: (28) Connection timed out after 2002 milliseconds |
| 242 | +$ curl --connect-timeout 2 <server_2> |
| 243 | +curl: (28) Connection timed out after 2002 milliseconds |
| 244 | +``` |
| 245 | + |
| 246 | +You can also check on the central server that everything is working correctly: |
| 247 | + |
| 248 | +```bash |
| 249 | +$ sudo cscli metrics |
| 250 | +───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ |
| 251 | +│ Acquisition Metrics │ |
| 252 | +├─────────────────────────────────────────────────────┬────────────┬──────────────┬────────────────┬────────────────────────┬───────────────────┤ |
| 253 | +│ Source │ Lines read │ Lines parsed │ Lines unparsed │ Lines poured to bucket │ Lines whitelisted │ |
| 254 | +├─────────────────────────────────────────────────────┼────────────┼──────────────┼────────────────┼────────────────────────┼───────────────────┤ |
| 255 | +│ file:/var/log/remote-logs/ip-172-31-11-52/auth.log │ 5 │ - │ 5 │ - │ - │ |
| 256 | +│ file:/var/log/remote-logs/ip-172-31-11-52/nginx.log │ 1 │ 1 │ - │ 1 │ - │ |
| 257 | +│ file:/var/log/remote-logs/ip-172-31-3-141/auth.log │ 3 │ - │ 3 │ - │ - │ |
| 258 | +│ file:/var/log/remote-logs/ip-172-31-3-141/nginx.log │ 99 │ 99 │ - │ 195 │ - │ |
| 259 | +│ file:/var/log/syslog │ 3 │ - │ 3 │ - │ - │ |
| 260 | +╰─────────────────────────────────────────────────────┴────────────┴──────────────┴────────────────┴────────────────────────┴───────────────────╯ |
| 261 | +``` |
| 262 | + |
| 263 | +And view the current decisions: |
| 264 | + |
| 265 | +```bash |
| 266 | +$ sudo cscli decisions list |
| 267 | +╭───────┬──────────┬──────────────────┬──────────────────────────────────────┬────────┬─────────┬────────────────┬────────┬────────────┬──────────╮ |
| 268 | +│ ID │ Source │ Scope:Value │ Reason │ Action │ Country │ AS │ Events │ expiration │ Alert ID │ |
| 269 | +├───────┼──────────┼──────────────────┼──────────────────────────────────────┼────────┼─────────┼────────────────┼────────┼────────────┼──────────┤ |
| 270 | +│ 30011 │ crowdsec │ Ip:X.X.X.X │ crowdsecurity/http-crawl-non_statics │ ban │ FR │ 12322 Free SAS │ 43 │ 3h57m29s │ 14 │ |
| 271 | +╰───────┴──────────┴──────────────────┴──────────────────────────────────────┴────────┴─────────┴────────────────┴────────┴────────────┴──────────╯ |
| 272 | +``` |
| 273 | + |
| 274 | +You can delete the decision with `cscli decision delete` to regain access to the web servers. |
0 commit comments