grok, parse iptables remote log - logstash

I am new with grok and haven't work with grok before, but now, I need a help.
I have remote log message from remote system which contains iptables rules.
May 11 09:37:05 zabbix kernel: [1607613.428683] FW_F_IN_DROP: IN=ens18 OUT= MAC=3a:e9:5f:c7:41:78:d0:07:ca:8c:10:01:08:00 SRC=104.16.55.12 DST=9.0.20.11 LEN=40 TOS=0x00 PREC=0x00 TTL=243 ID=36679 PROTO=TCP SPT=58399 DPT=8427 WINDOW=1024 RES=0x00 SYN URGP=0
I found a rule:
((%{SYSLOGTIMESTAMP:nf_timestamp})\s*(%{HOSTNAME:nf_host})\s*kernel\S+\s*(%{WORD:nf_action})?.*IN=(%{USERNAME:nf_in_interface})?.*OUT=(%{USERNAME:nf_out_interface})?.*MAC=(%{COMMONMAC:nf_dst_mac}):(%{COMMONMAC:nf_src_mac})?.*SRC=(%{IPV4:nf_src_ip}).*DST=(%{IPV4:nf_dst_ip}).*PROTO=(%{WORD:nf_protocol}).?*SPT=(%{INT:nf_src_port}?.*DPT=%{INT:nf_dst_port}?.*))
I like this rule, but output of this rule doesn't contain a string from iptables:
-j LOG --log-prefix "my log prefix"
which in this case equal to: FW_F_IN_DROP
also, what is the best solution to parse: [1607613.428683], looks like this is a kernel pid, but included also point in the middle
Can someone help me to modify this rule to include also log prefix information.
Thank you.

You grab an additional word in your pattern with %{WORD:log_prefix}:
The modified filter would look like this:
((%{SYSLOGTIMESTAMP:nf_timestamp})\s*(%{HOSTNAME:nf_host})\s*kernel\S+\s*(%{WORD:nf_action})?.*%{WORD:log_prefix}: IN=(%{USERNAME:nf_in_interface})?.*OUT=(%{USERNAME:nf_out_interface})?.*MAC=(%{COMMONMAC:nf_dst_mac}):(%{COMMONMAC:nf_src_mac})?.*SRC=(%{IPV4:nf_src_ip}).*DST=(%{IPV4:nf_dst_ip}).*PROTO=(%{WORD:nf_protocol}).?*SPT=(%{INT:nf_src_port}?.*DPT=%{INT:nf_dst_port}?.*))
The parsing of your log will add the following field:
"log_prefix": "FW_F_IN_DROP"

Related

Linux: how to get network stats on tcp (ie excluding udp)?

I've been using /sys/class/net/eno1/statistics/rx_bytes and tx_bytes to gather stats on my network interface. The trouble is, that network has a device (a Silicon Dust HDHOMERUN HDTV tuner) which constantly streams UDP packets at a very high rate that I don't want to monitor. I'd like to remove that traffic from the monitor - perhaps by only looking at TCP packets.
Is there any way to separate out the TCP and UDP stats?
netstat -st gives some info but it's somewhat cryptic - just how big is a 'segment'? The MTU? The man page is silent on that.
$ netstat -st | grep 'segments received'
25449056 segments received
1683 bad segments received
$ netstat -st | grep 'segments sent out'
37860139 segments sent out
Based on this answer from serverfault. If you are using iptables you can add a rule to each of the INPUT and OUTPUT chains which will count every packet which carries TCP in the payload. It is possible that you will need to invoke every iptables command with sudo.
Create the rules:
# Match all TCP-carrying packets incoming on 'eno1' iface
iptables -I INPUT -i eno1 -p tcp
# Match all TCP-carrying packets outgoing through 'eno1' iface
iptables -I OUTPUT -o eno1 -p tcp
Afterwards, you can use iptables -nvxL INPUT or OUTPUT to be presented with the number of bytes processed by the rule:
Chain INPUT (policy ACCEPT 9387 packets, 7868103 bytes)
pkts bytes target prot opt in out source destination
10582 9874623 tcp -- eno1 * 0.0.0.0/0 0.0.0.0/0
In case you already have other rules defined it might be handy to create a separate chain entirely. This is also described in the answer i referenced, though you also want the -i and -o options in the in/out chains respectively. These allow you to filter on a single interface (use -i for INPUT and -o for OUTPUT).
iptables -N count_in # create custom chain named 'count_in'
iptables -A count_in -j RETURN # append RETURN action to chain 'count_in'
iptables -I INPUT -j count_in # insert chain at the top of chain INPUT
iptables -I count_in 1 -i eno1 -p tcp # insert rule that matches all tcp packets on eno1
# and has no action (does nothing)
iptables -nvxL count_in # list chain 'count_in' rules
I am not sure whether the "bytes" counter includes the IP header, or just the TCP segment bytes but it is still probably the closest metric to what you want to measure (TCP-only rx/tx bytes).
Additionally keep in mind that oftentimes rules defined with iptables are not actually saved and will get deleted on a system reboot. To enable them persistently on every reboot you may use the iptables-save and iptables-restore commands. To learn their usage you should probably look in your Linux distro's documentation as well as iptables manual.
Finally, AFAIK iptables is considered legacy by now and it is being slowly replaced by nftables. I myself still have iptables installed in my system by default. If you want to switch/are already using nftables, then you need to translate above commands to the syntax supported by the nft command. There is a utility called iptables-translate available which may help with this. It's purpose is to translate old iptables commands to equivalent nft commands. I mention this mostly for the sake of completeness, you should be just fine using iptables for your particular task if you have it installed.
You can use iptraf-ng.
Install with:
sudo apt install iptraf-ng
This will give you statistics per protocol (IPv4/IPv6/TCP/UDP/ICMP/...) on a specific interface:
sudo iptraf-ng -d eth0
You can also use this to have details per ports:
sudo iptraf-ng -s eth0

Logging all connections using iptables to closed ports

In FreeBSD, there is a kernel parameter tweakable via sysctl (net.inet.tcp.log_in_vain) that provides you with logs of attempted connections to ports which are not running a service (i.e. closed ports). These messages are logged to /var/log/messages (somewhat) in the following format:
2014-06-26 13:18:58|218.77.79.43|58848|192.168.192.28|443|tcp_input: Connection attempt to closed port
Without forwarding all connections from router to my FreeBSD box, I get these messages on a regular basis. How is this happening if I haven't explicitly created port-forward rulesets redirecting traffic to this box on the router?
I'm looking to set up something similar using iptables, reducing as much noise as possible e.g. only see connections for those originating outside of my network as src and ignore any outgoing.
I was attempting to use something like the following to do this:
iptables -I INPUT -m state --state NEW -j LOG --log-prefix "New Connection: "
I'm pretty sure this syntax is fairly outdated. I come from an IPF world so I'm not quite up to speed with the latest iptables syntax conventions.
This rule is generating the type of logs I'm looking for in /var/log/messages:
Jun 28 00:38:12 kermit kernel: [ 6331.339928] New Connection: IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:a8:86:dd:8a:c9:26:08:00:45:00:00:48:e8:3f:00:00:40:11:8f:ec │
SRC=192.168.192.40 DST=192.168.192.255 LEN=72 TOS=0x00 PREC=0x00 TTL=64 ID=59455 PROTO=UDP SPT=57621 DPT=57621 LEN=52
Thus far, I haven't seen any connections from outside of my own network. Additionally, I can see SSH login attempts in /var/log/auth.log which are not appearing in /var/log/messages using the above iptables rule:
Jun 28 09:31:42 kermit sshd[10097]: pam_unix(sshd:auth): check pass; user unknown
Jun 28 09:31:44 kermit sshd[10097]: Failed password for invalid user admin from 116.10.191.187 port 40312 ssh2
Is it possible using iptables to create the following:
A rule/ruleset which logs all incoming connections to my box to /var/log/messages
Don't log any connections originating from within my own network
Don't log any outgoing connections
Am I required to forward all connections on the router to my box in order to get similar log messages as I did in FreeBSD? (i.e. port-forward all ports)
I found the following (basic) rulset did what I was looking for:
# Generated by iptables-save v1.4.14 on Sat Jun 28 14:02:33 2014
*filter
:INPUT ACCEPT [586:43405]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [367:72794]
:LOGNDROP - [0:0]
-A INPUT ! -s 192.168.192.0/24 -p tcp -m state --state NEW -j LOG --log-prefix "[New Connection]: "
COMMIT
# Completed on Sat Jun 28 14:02:33 2014

rsyslog - Property-based filtering not working

I almost hate to submit a topic for this, but I haven't been able to figure it out on my own. I'm running a Federoa 17 server, and I'm attempting to log dropped packets from iptables to a separate log file via rsyslog, but it keeps sending them to /var/log/messages instead.
Snippet from my firewall script:
#!/bin/bash
iptables -F
# My accepted rules would be here
iptables -A INPUT -j LOG --log-prefix "iptables: "
iptables -A FORWARD -j LOG --log-prefix "iptables: "
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables-save > /etc/sysconfig/iptables
service iptables restart
iptables -L -v
The config file that SHOULD be catching the messages from iptables:
[root#fc17 ]# cat /etc/rsyslog.d/iptables.conf
:msg, startswith, "iptables: " /var/log/iptables.log
& ~
Snippet from my rsyslog.conf file:
#### GLOBAL DIRECTIVES ####
# Include all config files in /etc/rsyslog.d/
$IncludeConfig /etc/rsyslog.d/*.conf
#### RULES ####
# I put this in here too to see if it would work; it doesn't
:msg, startswith, "iptables: " /var/log/iptables.log
& ~
# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.* /dev/console
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none /var/log/messages
I've restarted both iptables and rsyslog multiple times since making the changes, and no matter what, it will only only log dropped packets from iptables to /var/log/messages.
I heard running rsyslog in compatibility mode can cause various problems. Could this be the case here? Here are its run-options on my system:
[root#fc17 ]# ps -ef | grep rsyslog
root 3571 1 0 00:59 ? 00:00:00 /sbin/rsyslogd -n -c 5
startswith comparison operator didn't work,because msg didn't begin with iptables: when i checked my logs.
[root#localhost ~]# cat /etc/rsyslog.d/test.conf
:msg, startswith, "iptables:" /var/log/iptables.log
but contains comparison operator worked on my FC18
[root#localhost ~]# cat /etc/rsyslog.d/test.conf
:msg, contains, "iptables:" /var/log/iptables.log
Ref: Rsyslog site
you should add the following two line in your "/etc/rsyslogd.conf" in directives part
$klogParseKernelTimestamp on
$klogKeepKernelTimestamp off
This will remove the kernel timestamp which appears in the begining of every kernel message like "[6448.546951]" in the following log
Mar 31 14:36:14 localhost kernel: [ 6448.546951] iptables: IN=ppp0 OUT= MAC= SRC=
2019 solution. Tested with rsyslogd 8.32.0 on Ubuntu18.04.
You can still use startswith,
[root#localhost ~]# cat /etc/rsyslog.d/test.conf
:msg, startswith, " iptables:" /var/log/iptables.log
by changing the line in /etc/rsyslogd.conf
module(load="imklog" ParseKernelTimestamp="on" KeepKernelTimestamp="off")
I'm using rsyslogd 5.8.10 over centos 6, my log report show this way:
Aug 12 11:50:41 node2 kernel: [10256396.525411] IPTables-Dropped: IN=eth0 OUT= MAC=00:25:90:c3:05:40:00:24:13:10:8c:00:08:00 SRC=212.237.40.56 DST=37.153.1.29 LEN=45 TOS=0x00 PREC=0x00 TTL=244 ID=54321 PROTO=UDP SPT=45661 DPT=53413 LEN=25
I tried to disabled the timestamp with:
$klogParseKernelTimestamp on
$klogKeepKernelTimestamp off
But show:
Aug 12 11:50:22 node2 rsyslogd-3003: invalid or yet-unknown config file command - have you forgotten to load a module? [try http://www.rsyslog.com/e/3003 ]
In modules have this:
#### MODULES ####
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imklog # provides kernel logging support (previously done by rklogd)
#$ModLoad immark # provides --MARK-- message capability
Thank you advance.

Creating firewall rules using iptables

Is there any way to construct a firewall rule using "iptables" which filters packets on both input and output? I've only been able to find rules like the following which allow you to designate it as applying to packet source (INPUT) or destination (OUTPUT).
iptables -A INPUT -i eth1 -p tcp -s 192.168.1.0/24 --dport 80 -j DROP.
It would make sense though that I should be able to filter packets coming from and going to specific places so that I could end up with a fw table like the following:
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * * 172.152.4.0/24 92.3.0.0/16
Any suggestions?
Thanks!
Yes and no.
No because: iptables works by defining how to treat packets based on their categorization into chains (INPUT, OUTPUT, FORWARD, ...) first and only then also on specific characteristics (source or destination address, protocol type, source or destination port, etc). You can never define an iptable rule that does not apply to a specific chain.
INPUT, OUTPUT, and FORWARD are the default chains of the iptables system. INPUT addresses everything with destination localhost (i.e. that is addressed to your network device); OUTPUT applies to everything with source localhost (i.e. that comes from your computer).
Yes because: You can define custom chains. You can do that like so
sudo iptables -N MYCHAIN
then you can send packets from both the INPUT and the OUTPUT (and if you like the FORWARD) chain to MYCHAIN, for instance all the TCP packages from INPUT:
sudo iptables -A INPUT -p tcp -j MYCHAIN
or all the packages from OUTPUT
sudo iptables -A OUTPUT -j MYCHAIN
and then you can define any rule you want for mychain, including
sudo iptables -A MYCHAIN -s 172.152.4.0/24 -d 92.3.0.0/16 -j ACCEPT
which should be more or less the rule you wanted
However, one might argue that it does indeed make sense to keep INPUT and OUTPUT chains seperate. Most users will want to apply much stricter rules on INPUT and FORWARD than on OUTPUT. Also, iptables can be used for routing in which case it makes a fundamental difference if you have an incoming or an outgoing package.

Identify other end of a unix domain socket connection

I'm trying to figure out what process is holding the other end of a unix domain socket. In some strace output I've identified a given file descriptor which is involved in the problem I'm currently debugging, and I'd like to know which process is on the other end of that. As there are multiple connections to that socket, simply going by path name won't work.
lsof provides me with the following information:
dbus-daem 4175 mvg 10u unix 0xffff8803e256d9c0 0t0 12828 #/tmp/dbus-LyGToFzlcG
So I know some address (“kernel address”?), I know some socket number, and I know the path. I can find that same information in other places:
$ netstat -n | grep 12828
unix 3 [ ] STREAM CONNECTED 12828 #/tmp/dbus-LyGToFzlcG
$ grep -E '12828|ffff8803e256d9c0' /proc/net/unix
ffff8803e256d9c0: 00000003 00000000 00000000 0001 03 12828 #/tmp/dbus-LyGToFzlcG
$ ls -l /proc/*/fd/* 2>/dev/null | grep 12828
lrwx------ 1 mvg users 64 10. Aug 09:08 /proc/4175/fd/10 -> socket:[12828]
However, none of this tells me what the other end of my socket connection is. How can I tell which process is holding the other end?
Similar questions have been asked on Server Fault and Unix & Linux. The accepted answer is that this information is not reliably available to the user space on Linux.
A common suggestion is to look at adjacent socket numbers, but ls -l /proc/*/fd/* 2>/dev/null | grep 1282[79] gave no results here. Perhaps adjacent lines in the output from netstat can be used. It seems like there was a pattern of connections with and without an associated socket name. But I'd like some kind of certainty, not just guesswork.
One answer suggests a tool which appears to be able to address this by digging through kernel structures. Using that option requires debug information for the kernel, as generated by the CONFIG_DEBUG_INFO option and provided as a separate package by some distributions. Based on that answer, using the address provided by lsof, the following solution worked for me:
# gdb /usr/src/linux/vmlinux /proc/kcore
(gdb) p ((struct unix_sock*)0xffff8803e256d9c0)->peer
This will print the address of the other end of the connection. Grepping lsof -U for that number will provide details like the process id and the file descriptor number.
If debug information is not available, it might be possible to access the required information by knowing the offset of the peer member into the unix_sock structure. In my case, on Linux 3.5.0 for x86_64, the following code can be used to compute the same address without relying on debugging symbols:
(gdb) p ((void**)0xffff8803e256d9c0)[0x52]
I won't make any guarantees about how portable that solution is.
Update: It's been possible to to do this using actual interfaces for a while now. Starting with Linux 3.3, the UNIX_DIAG feature provides a netlink-based API for this information, and lsof 4.89 and later support it. See https://unix.stackexchange.com/a/190606/1820 for more information.

Resources