Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

graylog2 output get messy after a few seconds #4792

Open
frhack opened this issue Jan 18, 2024 · 21 comments
Open

graylog2 output get messy after a few seconds #4792

frhack opened this issue Jan 18, 2024 · 21 comments
Labels

Comments

@frhack
Copy link

frhack commented Jan 18, 2024

syslog-ng

Version of syslog-ng

syslog-ng 4 (4.4.0)

Platform

Linux Ubuntu 22.04.3 LTS x86_64

Issue

I configured a graylog2 destination (graylog is on the same host) as follow

destination d_graylog {
        graylog2(
                host("127.0.0.1")
                transport("udp")
        );
};

Everything works fine for a few seconds (10 / 20 seconds) then syslogng starts sending data in wrong format: graylog2 starts complaining of the wrong format and I verified with tcpdump that after a few seconds the format change.

If I restart syslogng the output format come back correct, but after a few seconds it becomes wrong again. The format is correct only for a few seconds after a syslogng start/restart.

Thanks.

Graylog errors follow:

2024-01-18T12:18:14.101+01:00 ERROR [DecodingProcessor] Unable to decode raw message RawMessage{id=4564d320-b5f3-11ee-99fe-eeec2b73f2fe, messageQueueId=73299206, codec=gelf, payloadSize=65507, timestamp=2024-01-18T11:18:14.098Z, seqenceNr=428786, remoteAddress=/127.0.0.1:53535} on input <65a7cdf60b2ebf167d8e446a>.
2024-01-18T12:18:14.102+01:00 ERROR [DecodingProcessor] Error processing message RawMessage{id=4564d320-b5f3-11ee-99fe-eeec2b73f2fe, messageQueueId=73299206, codec=gelf, payloadSize=65507, timestamp=2024-01-18T11:18:14.098Z, seqenceNr=428786, remoteAddress=/127.0.0.1:53535}
com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting closing quote for a string value
 at [Source: (StringReader); line: 1, column: 65508]
        ...
2024-01-18T12:18:14.310+01:00 ERROR [GelfCodec] Could not parse JSON, first 400 characters: {"version":"1.1","timestamp":1705576694,"short_message":"FTNTFGTtz=###### FTNTFGTlogid=###### cat=traffic:forward FTNTFGTsubtype=forward FTNTFGTlevel=notice FTNTFGTvd=root src=####### spt=##### deviceInboundInterface=######### FTNTFGTsrcintfrole=lan dst=####### dpt=80 deviceOutboundInterface=###### FTNTFGTdstintfrole=wan FTNTFGTsrccountry=Reserved FTNTFGTdstcountry=##### externalId=#####...
com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting closing quote for a string value
 at [Source: (StringReader); line: 1, column: 65508]
        ...
2024-01-18T12:18:14.311+01:00 ERROR [DecodingProcessor] Unable to decode raw message RawMessage{id=4584b730-b5f3-11ee-99fe-eeec2b73f2fe, messageQueueId=73299207, codec=gelf, payloadSize=65507, timestamp=2024-01-18T11:18:14.307Z, seqenceNr=428787, remoteAddress=/127.0.0.1:53535} on input <65a7cdf60b2ebf167d8e446a>.

@frhack frhack added the bug label Jan 18, 2024
@bazsi
Copy link
Collaborator

bazsi commented Jan 20, 2024 via email

@frhack
Copy link
Author

frhack commented Jan 22, 2024

Hi, Can you send me the samples? Eg. The good formatting and the way it changes. Thanks

Thanks for the support.

After a restart I execute this command

sudo tcpdump -X -s0 -nn -v -i any udp port 12201 -s 16000 -w - | awk '{print}' RS='<189' -

and I see:

$some_binary_chars{$json_like_properties ... "short_message": "...."} $some_binary_chars{$json_like_properties ... "short_message": "...."} $some_binary_chars{$json_like_properties ... "short_message": "...."}
... and so on

where: $some_binary_chars is a placeholder for some binary chars
$json_like_properties is a placeholder for json like properties

after a while the format change:

It seems it starts sending only the content of the "json" field "short_message".
No more binary chars and no more json like properties

(SyslogNg receives a CEF stream and sends it to Graylog)

...I hope this is enough in order to investigate the problem

thanks

@alltilla
Copy link
Collaborator

From the error logs, I get the feeling that the JSON data is truncated.

com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting closing quote for a string value
 at [Source: (StringReader); line: 1, column: 65508]

GELF over UDP supports only 64K sized messages: https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html#GELFviaUDP

syslog-ng has not implemented UDP chunking for the graylog2() destination.

Is it possible to use TCP in your scenario? I think it would fix the problem. If not, we would need to have the GELF UDP chunking implemented in syslog-ng, but that would take some time, unfortunately.

@frhack
Copy link
Author

frhack commented Jan 24, 2024

Thank you,

unfortunately I'm using UDP because in TCP there are other problems (maybe in the Graylog side or in the source) that cause many CEF messages to be received as one message.

What I don't understand is why in UDP everything works fine but only for a few seconds.

How can this work if, as you say, syslog-ng has not implemented UDP Chunking for the graylog2() target?

Thank you

From the error logs, I get the feeling that the JSON data is truncated.

com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: was expecting closing quote for a string value
 at [Source: (StringReader); line: 1, column: 65508]

GELF over UDP supports only 64K sized messages: https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html#GELFviaUDP

syslog-ng has not implemented UDP chunking for the graylog2() destination.

Is it possible to use TCP in your scenario? I think it would fix the problem. If not, we would need to have the GELF UDP chunking implemented in syslog-ng, but that would take some time, unfortunately.

@alltilla
Copy link
Collaborator

What I don't understand is why in UDP everything works fine but only for a few seconds.

Maybe log messages are starting small (below 64K), and getting larger after a couple of seconds, but that is just a guess.

You can check what exactly gets sent to graylog by switching to a file() destination:

destination d_graylog {
#        graylog2(
#                host("127.0.0.1")
#                transport("udp")
#        );
        file(
                "/tmp/graylog-test.log"
                template("$(format-gelf)\n")
        );
};

Each line is what goes into one UDP packet. If my theory is right, after a couple of seconds you should see some really long lines after a couple of seconds, and those messages cause the issue when sending to graylog.

How can this work if, as you say, syslog-ng has not implemented UDP Chunking for the graylog2() target?

A simple GELF over UDP below 64K message size does not need UDP Chunking. If we implemented UDP Chunking, we would solve this 64K issue.

@frhack
Copy link
Author

frhack commented Jan 24, 2024

You can check what exactly gets sent to graylog by switching to a file() destination:

destination d_graylog {
#        graylog2(
#                host("127.0.0.1")
#                transport("udp")
#        );
        file(
                "/tmp/graylog-test.log"
                template("$(format-gelf)\n")
        );
};

I tried and this is the result.
The file starts with correct lines: in a line I have exactly one short_message and one CEF message

After a while the format change.
In one line I have one short_message with many CEF messages. The number of grouped CEF messages is variable: 51,53,55, 50,48,52... It seams very near to 50

@bazsi
Copy link
Collaborator

bazsi commented Jan 24, 2024

Hmmm, maybe the problem is on the receiving side, then?

64k is a huge message size, so maybe the CEF side is at fault here.

For instance the end of message there may not be recognized and a whole bunch of cef messages end up in a single, huge message.

Can you post your source driver declaration and maybe a capture of the input?

@frhack
Copy link
Author

frhack commented Jan 24, 2024

The messages are very shorts something like 1000 characters, the problem is that after a while they get grouped together

How can I capture the input ?

@frhack
Copy link
Author

frhack commented Jan 24, 2024

The source is very simple:

source s_src { udp( port(514)); tcp( port(514));};

log { source(s_src); filter(f_to_graylog); destination(d_graylog); };

filter f_to_graylog {
 host(x.y.z);
};


@bazsi
Copy link
Collaborator

bazsi commented Jan 24, 2024

That seems to indicate that it is indeed the source that is at fault.

There are two ways to capture this

  1. use tcpdump just like you did before, but this time looking at the input port

  2. run syslog-ng in the foreground with debugging enabled (-Fed command line arguments) and save its output. There's an "Incoming" message on the debug level that should show you what syslog-ng considers a single message.

If the input does not terminate log lines or if syslog-ng is configured differently than the sender, something like this may happen. Effectively concatenating the input into one huge message.

The sample is needed to make sure there's some form of record separation on the input and that syslog-ng is using the same expectation.

@frhack
Copy link
Author

frhack commented Jan 24, 2024

That seems to indicate that it is indeed the source that is at fault.

There are two ways to capture this

  1. use tcpdump just like you did before, but this time looking at the input port
  2. run syslog-ng in the foreground with debugging enabled (-Fed command line arguments) and save its output. There's an "Incoming" message on the debug level that should show you what syslog-ng considers a single message.

If the input does not terminate log lines or if syslog-ng is configured differently than the sender, something like this may happen. Effectively concatenating the input into one huge message.

The sample is needed to make sure there's some form of record separation on the input and that syslog-ng is using the same expectation.

I capured the input using syslog-ng in foreground.

I see the same behaviour: some Incoming log entry contains many CEF entry so the line is very long.

Normal lines, at the beginning of the file (fresh start), contain only one CEF entry,

Is this normal ?

@frhack
Copy link
Author

frhack commented Jan 24, 2024

Here is the line size of "Incoming log entry" lines

1109
971
1075
1515
1047
974
930
1373
1147
1316
1366
1212
65627
65627
65627

at some point after starting syslog_ng line sizes become huge and stay huge

@bazsi
Copy link
Collaborator

bazsi commented Jan 25, 2024

No. and that's a clear indication of the problem. syslog-ng's default log-msg-size() parameter is 64k and I guess the incoming messages are all coalesced into a huge message and we are splitting them up at 64k

So my assumption: he issue is that your source device is not sending a newline character between messages

But I can only confirm if you send me at least one of your "Incoming message" lines. Or look into a separator character between the records and see for yourself.

syslog-ng's tcp or network driver would expect a newline (or NUL) character there. If there's nothing then the peer needs to be configured properly. But again, I can only help here if you share the message, possibly in private.

@frhack
Copy link
Author

frhack commented Jan 25, 2024

No. and that's a clear indication of the problem. syslog-ng's default log-msg-size() parameter is 64k and I guess the incoming messages are all coalesced into a huge message and we are splitting them up at 64k

So my assumption: he issue is that your source device is not sending a newline character between messages

But I can only confirm if you send me at least one of your "Incoming message" lines. Or look into a separator character between the records and see for yourself.

syslog-ng's tcp or network driver would expect a newline (or NUL) character there. If there's nothing then the peer needs to be configured properly. But again, I can only help here if you share the message, possibly in private.

Thank you for the support.

I found a work around. If I send the CEF stream to syslog_ng in UDP (instead of TCP) the problem vanish.

I'm not shure but I think I can opt for CEF UDP and keeep this workaround

Unfortunately I cannot send the log (tcpdump output) outside this network, I could obfuscate the logs, but I don'have a script at hand in order to manage this.

@frhack
Copy link
Author

frhack commented Jan 25, 2024

Now in UDP I have another problem.

Syslog_ng modify the message and send as:
"short_message":"0| .................. "_program":"CEF","_facility":"local7"}

instead of

"short_message":"CEF:0| ..................

It seems that if syslog_ng receive CEF messages in TCP sends as

"short_message":"CEF:0| ..................

if it receice CEF messages in UDP sends as

"short_message":"0| .................. "_program":"CEF","_facility":"local7"}

@bazsi
Copy link
Collaborator

bazsi commented Jan 25, 2024 via email

@frhack
Copy link
Author

frhack commented Jan 26, 2024

You might want to specify flags(no-parse) as you are clearly not receiving syslog. What's the sending application? It might be easier to help you that way

Thank you,
the source application is Fortigate.

What is the reason why if the source comes in UDP, Syslog-ng parses the messages and if the source is in TCP it doesn't?

@bazsi
Copy link
Collaborator

bazsi commented Jan 27, 2024

In UDP, every datagram is a separate message

In TCP, log messages follow each other within the tcp stream. The separation between messages is the NL character, just as with simple text files.

Since you didn't share the input I don't know if fortigate indeeds inserts a newline character after every message or not.

@frhack
Copy link
Author

frhack commented Jan 31, 2024

I switched to UDP with

In UDP, every datagram is a separate message

In TCP, log messages follow each other within the tcp stream. The separation between messages is the NL character, just as with simple text files.

Since you didn't share the input I don't know if fortigate indeeds inserts a newline character after every message or not.

As a workaround I switched to UDP with flags(no-parse) .

I suppose the problem was in Fortigate side as the following message.

https://community.graylog.org/t/fortinet-fortigate-tcp-raw-input-and-delimiter/17184

I suspected it was a syslog-ng problem because after a syslog-ng restart the messages are splitted correctly for the first 20 seconds approx.

Thanks for the support

@bazsi
Copy link
Collaborator

bazsi commented Feb 3, 2024

What is the "mode" setting on the fortigate side?

https://docs.fortinet.com/document/fortigate/7.0.13/cli-reference/393620/config-log-syslogd-setting

I guess now you are using udp. But when you were using tcp, what was the setting? "reliable" ?

According to this article: https://community.fortinet.com/t5/FortiGate/Troubleshooting-Tip-FortiGate-syslog-via-TCP-and-log-parsing/ta-p/198397

fortigate will send octet counted messages over simple TCP.

That can be received by syslog-ng, using the syslog() driver.

I was using this config to parse that format:

@version: current

log {
	source { syslog(port(6514) transport(tcp)); };

	destination {stdout(); };
};

@bazsi
Copy link
Collaborator

bazsi commented Feb 3, 2024

this should resolve the input side issues and let you properly process logs from fortigate, at least with its "mode" setting set to "reliable"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants