Showing posts with label SSL. Show all posts
Showing posts with label SSL. Show all posts

Tuesday, September 1, 2020

Testing Logstash Data Ingest

 By Tony Lee

When setting up an Elasticsearch Logstash Kibana (ELK) stack, you may discover the need to test your Logstash filters. There are probably many ways to accomplish this task, but we will cover some techniques and potential pitfalls in this article. 

Note: This article can be used to simulate any syslog replay for manual data ingest testing, but our example specifically covers Logstash as the receiver and a fabricated, but realistic, event.

Real-time Visibility

The first thing that will aid us in this ingest testing is real-time feedback. This could come from at least two potential places:

1)  "Real-time" discovery search within the Kibana UI

This is accomplished by using the discovery dashboard, setting a search term you know to be in your test message, and a short refresh rate as shown in the screenshot below.

Figure 1:  Kibana "Real-time" search using refresh interval


2) Monitoring the logstash log file for warnings or errors

For this, we will use the tail command with the follow option (-f) to watch it in real-time.  The location of your Logstash log may differ so adjust the path as necessary.

tail -f /var/log/logstash/logstash-plain.log

We are looking for clues that may have prevented proper ingest such as:

[2020-08-31T20:25:21,997][WARN ][logstash.filters.mutate][main][b14e-snip-a422] Exception caught while applying mutate filter {:exception=>"Could not set field 'name' on object 'compute-this' to value 'see-this'.This is probably due to trying to set a field like [foo][bar] = someValuewhen [foo] is not either a map or a string"}


Encrypted or Unencrypted Listener

Once we have real-time visibility in place, we need to determine if the listening port is expecting encrypted data since this will determine how we replay traffic to it. There are a few ways to determine this:

1) Check the logstash filter config file

The example below, is an example of an encrypted port.  We can see that is the case because we are defining the SSL information and have ssl_enable set to true.

input {

  tcp {

    port => 6514

    ssl_enable => true

    ssl_cert => "/etc/logstash/logstash.crt"

    ssl_key => "/etc/logstash/logstash.key"

    ssl_verify => false

  }

}


2) Check the logstash logs for SSL errors

If you have an encrypted listener and you send data using an unencrypted transport method (such as telnet), you will see SSL errors such as the following:

[2020-09-01T13:46:20,758][ERROR][logstash.inputs.tcp][main][359d9-snip-c5038d] Error in Netty pipeline: io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER


3) Use a tool (such as openssl) to verify the SSL connection

Below is an example of checking the SSL connection using openssl, but other tools can be used.

openssl s_client -connect <logstash_host>:6514

If the listener is expected encrypted data, you will see details such as certificate subject, issuer, cipher suites and more.

--snip--

subject=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd

issuer=C = AU, ST = Some-State, O = Internet Widgits Pty Ltd

--snip--

SSL handshake has read 1392 bytes and written 437 bytes

Verification error: self signed certificate

--snip--


Methods of Replay

Now that we have real-time visibility and we know if the listener is expecting encrypted data or not, we can look at different techniques to replay the traffic. We will start with unencrypted methods first because we can later tunnel the unencrypted data to an encrypted listener. We will also examine replaying an entire packet (including the header) vs. replaying just the data and having the header added.

1) Unencrypted replay of an exact packet (Included specified time and no addition of a header)

If you have example logs that you can expect that include the date/time format, you can replay the exact message using netcat/ncat.  Keep in mind that you are most likely sending a static time, so you will need set your Kibana time range appropriately.

First, place the contents of your event in a test file, we created a file called testevent.txt with the following contents (notice the included date and time):

<46>1 2020-08-31T02:08:08.988000Z sysloghost ExtraField - - [Location] Event Type: OurTest, Event Name: Blocked, Device Name: DESKTOPTESTLOGGER2, File Path: C:\Windows\system32\foo.ps1,  Interpreter: Powershell, Interpreter Version: 10.0.18362.1 (WinBuild.160101.0800), User Name: SYSTEM, Device Id: 4eaf3350a984


Second, use netcat or ncat to send the data to your listening port. The example shown below is sending to an unencrypted listener (be sure to replace logstash_host with the IP or hostname of your logstash server):

ncat <logstash_host> 6514 < testevent.txt

Then just monitor the logstash log and real-time search in Kibana to see the event and/or potential errors.

2) Encrypted replay of an exact packet (Included specified time and no addition of a header)

For this we will use the same testevent.txt file from above and nearly the same command, but we will add --ssl to force ncat to perform the encrypted handshake.

ncat --ssl <logstash_host> 6514 < testevent.txt


3) Unencrypted replay of an exact packet contents with an updated time

If you have packet contents, but want the header updated with the current time, you might be able to use the logger command in Linux.  The trick here is to get logger to reproduce your expected header. Use the following steps to attempt this:

Understand the logger options:

logger --help


Read in our test event and output to stderr for troubleshooting:

logger -s -f testevent.txt


Use logger options to alter the header (in our case, it was --rfc5424=notq) to match what we need and then create a new file with only the content and no header.  Ex:  testevent_noheader.txt

Figure 2:  Reproducing the event with an updated header

Send the event to the unencrypted listener and check for it in Kibana and Logstash logs:

logger --rfc5424=notq -s -f testevent_noheader.txt --server <logstash_host> --tcp --port 6515


4) Encrypted replay of an exact packet contents with an updated time

Unfortunately our version of logger does not have an option to enable encryption. So, if you were able to get logger to reproduce the header + content in the step above, but need to send it to an encrypted listener, you could once again use ncat to assist. The following command creates an unencrypted listener on your local host on port 6515--then anything written to that local port will be sent on in an encrypted state to port 6514.

Figure 3:  ncat listener to send data onto Logstash using SSL


Step 1) Create the listening wrapper:

ncat -l 6515 -c "ncat --ssl <logstash_host> 6514"


Step 2)  Send the packet to the wrapper using logger:

logger --rfc5424=notq -s -f testevent_noheader.txt --server localhost --tcp --port 6515


Conclusion

We are just scratching the surface in ways to test data ingest components such as Logstash. For instance, this could be expanded to include scripting with variables that are replaced with random data to generate more robust values. But that will be an exercise left to the user (or maybe a future article). We do hope this article proved useful and would love to know what you use for testing data ingest. Feel free to leave comments in the section below.  Thanks for reading.




Wednesday, September 18, 2019

Syslog Over TLS Data Feed Splitting via syslog-ng

By Tony Lee

There are times where you may only be able to send data to a single syslog receiver, but all is not lost. Fortunately, many syslog receivers can handle splitting the feed. In this article we will use syslog-ng to show the steps needed to split a syslog feed (possibly for the purpose of taking a single feed and sending it to two SIEMs).  As a bonus, we will give you the steps to also receive and split a TLS encrypted syslog feed.


Figure 1:  Unencrypted syslog feed splitting

Basic Requirements

Since we are not handling much volume in this example, we just need minimum requirements:

Our setup
  • Amazon EC2 instance
  • Ubuntu Server 18.04 LTS (Red Hat is also possible, but requires different commands)
  • 1 vCPU, 1GB RAM, 10GB HD

Basic Setup Steps

The syslog-ng package was not available out of the box for us so we had to run:

sudo apt update

Install and create a basic configuration file

sudo su -
apt install syslog-ng
mv syslog-ng.conf syslog-ng.bak
vim syslog-ng.conf

Note:  We used the same version found in the “Config version” field after running “syslog-ng --version”


@version: 3.13

source s_input { tcp(ip(0.0.0.0) port(10514)); };
destination d_siem{ udp("10.0.0.1" port(7514) template("$MSG") ); };
destination d_siem2{ tcp("10.0.0.2" port(7515) template("$MSG") ); };

log{
source(s_input);
destination(d_siem);
destination(d_siem2);
};


Configuration explanation:

  • template("$MSG") ensures that syslog-ng does not add another header to the message
  • Single input called s_input listening on all interfaces over TCP port 10514
  • Two destinations
1) d_siem sending to 10.0.0.1 on UDP 514
2) d_siem2 sending to 10.0.0.2 on TCP 515

Validate the configuration file
Use the following command to validate and troubleshoot syslog-ng configuration issues:

syslog-ng -s -f syslog-ng.conf


Start/restart the Service
Use the following command to check and restart the syslog-ng service:

service syslog-ng status
service syslog-ng restart


Validate the port is open
Use the following command to validate listening port is open:

netstat -an | grep :10514
tcp        0      0 0.0.0.0:10514           0.0.0.0:*               LISTEN


Test the Splitting
Since we are splitting TCP syslog in our example, we can use a web browser to test it:

http://<Your_syslog-ng_server>:10514


Figure 2:  Showing port details

Seeing the results in on the final server on UDP 7514 and TCP 7514


Figure 3:  Confirmation that the UDP 7514 split is working


Figure 4:  Confirmation that the TCP 7515 split is working

Enabling Syslog over TLS on the Input

We mentioned that there would be a bonus, now let’s enable TLS.
Note: This should be a requirement if your data is traversing a public network such as the Internet.

Creating private Certificate Authority (CA)
If you don’t have your own CA or choose not to use a public CA, you will need to create a CA on your syslog-ng server to sign certificates

sudo su –
cd /root
mkdir CA
cd CA
mkdir certs crl newcerts private
echo "01" > serial
cp /dev/null index.txt
cp /etc/ssl/openssl.cnf .
vi openssl.cnf

Change from:
dir = ./demoCA
to:
dir = .

:wq to save and exit vi

Generate the CA certificate
openssl req -new -x509 -keyout private/cakey.pem -out cacert.pem -days 365 -config openssl.cnf

Creating Server Certificate Request
Whether you use the local CA or an external/public CA, you will need to generate a server certificate request.

openssl req -nodes -new -x509 -keyout serverkey.pem -out serverreq.pem -days 365 -config openssl.cnf
openssl x509 -x509toreq -in serverreq.pem -signkey serverkey.pem -out tmp.pem

Common name should be the IP address or FQDN of your server. Leave email field blank.

Signing Server Certificate with CA
Next you can either get the serverreq.pem signed by your external CA, or sign it locally with the next step:

openssl ca -config openssl.cnf -policy policy_anything -out servercert.pem -infiles tmp.pem
rm tmp.pem

Either way you should end up with servercert.pem and serverkey.pem files, which will be used as
the server certificate and key for TLS encryption.

Copying Certificates to Syslog Directory

mkdir /etc/syslog-ng/cert.d
mkdir /etc/syslog-ng/key.d
mkdir /etc/syslog-ng/ca.d (if using local Certificate Authority)
cp cacert.pem /etc/syslog-ng/ca.d/ (if using local Certificate Authority)
cp servercert.pem /etc/syslog-ng/cert.d/
cp serverkey.pem /etc/syslog-ng/key.d/
cd /etc/syslog-ng/cert.d/
chown root servercert.pem
chmod 600 servercert.pem
cd /etc/syslog-ng/key.d/
chown root serverkey.pem
chmod 600 serverkey.pem
cd /etc/syslog-ng/ca.d/ (if using local Certificate Authority)
chown root cacert.pem (if using local Certificate Authority)
chmod 600 cacert.pem (if using local Certificate Authority)

Modify syslog-ng configuration file to use TLS
vim syslog-ng.conf


@version: 3.13

source s_input { tcp(ip(0.0.0.0) port(10514) tls(key_file("/etc/syslog-ng/key.d/serverkey.pem") cert_file("/etc/syslog-ng/cert.d/servercert.pem") peer_verify(optional-untrusted)) ); };
destination d_siem{ udp("10.0.0.1" port(7514) template("$MSG") ); };
destination d_siem2{ tcp("10.0.0.2" port(7515) template("$MSG") ); };

log{
source(s_input);
destination(d_siem);
destination(d_siem2);
};


Validate the configuration file
Use the following command to validate and troubleshoot syslog-ng configuration issues:

syslog-ng -s -f syslog-ng.conf


Start/restart the Service
Use the following command to check and restart the syslog-ng service:

service syslog-ng status
service syslog-ng restart

Test the Splitting
Since we are splitting TCP over TLS syslog in our example, we can use a web browser to test it:
https://<Your_syslog-ng_server>:10514



Figure 5:  TLS enabled on the Input

Enabling Syslog over TLS on the Input & Output

Let’s go for the double bonus now and enable TLS on the Input and TCP Output
Note: This should be a requirement if your data is traversing multiple public networks such as the Internet.

Modify syslog-ng configuration file to use TLS

vim syslog-ng.conf


@version: 3.13

source s_input { tcp(ip(0.0.0.0) port(10514) tls(key_file("/etc/syslog-ng/key.d/serverkey.pem") cert_file("/etc/syslog-ng/cert.d/servercert.pem") peer_verify(optional-untrusted)) ); };
destination d_siem{ udp("10.0.0.1" port(7514) template("$MSG") ); };
destination d_siem2{ tcp("10.0.0.2" port(7515) tls(key_file("/etc/syslog-ng/key.d/serverkey.pem") cert_file("/etc/syslog-ng/cert.d/servercert.pem") peer_verify(optional-untrusted)) template("$MSG") ); };

log{
source(s_input);
destination(d_siem);
destination(d_siem2);
};


Validate the configuration file
Use the following command to validate and troubleshoot syslog-ng configuration issues:

syslog-ng -s -f syslog-ng.conf


Start/restart the Service
Use the following command to check and restart the syslog-ng service:

service syslog-ng status
service syslog-ng restart

Test the Splitting
Since we are splitting TCP over TLS syslog in our example, we can use a web browser to test it:
https://<Your_syslog-ng_server>:10514


Figure 6:  TLS enabled on input and TCP output
Note:  We cannot TLS encrypt the UDP data stream

Set Service to Autostart on Boot

If all is well, now we can set the service to autostart at boot – just in case we experience a reboot.

sudo update-rc.d syslog-ng defaults

Added Security

Hopefully the source and destination IP addresses are static and known. This allows us to further protect the syslog ports by adding one to one firewall rules. This can be performed at both the network and host layer.

Caching Capabilities

One other option is to add some caching capabilities on this server by adding another destination of a local file. With enough disk space, it could provide some time to collect logs from the syslog-ng server before they rolled in the case of a network issue between the syslog-ng server and the downstream host.

Conclusion

In this article we showed how we can set up an intermediary syslog-ng server to split a single feed into multiple feeds. As a bonus, we also showed how we could secure the syslog traffic by enabling TLS to wrap the data with encryption. We hope this article helps get you up and running quicker when you need to split and secure that next feed.

Thanks

Zack Link for the original write up using Red Hat Linux. Syslog-ng team for the great software and documentation (https://www.syslog-ng.com/technical-documents/doc/syslog-ng-open-source-edition/3.16/mutual-authentication-using-tls#TOPIC-956369).