forked from influxdata/telegraf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The iptables plugin aims at monitoring bytes and packet counters matching a given set of iptables rules. Typically the user would set a dedicated monitoring chain into a given iptables table, and add the rules to monitor to this chain. The plugin will allow to focus on the counters for this particular table/chain. closes influxdata#1471
- Loading branch information
Showing
8 changed files
with
426 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Iptables Plugin | ||
|
||
The iptables plugin gathers packets and bytes counters for rules within a set of table and chain from the Linux's iptables firewall. | ||
|
||
Rules are identified through associated comment. Rules without comment are ignored. | ||
|
||
The iptables command requires CAP_NET_ADMIN and CAP_NET_RAW capabilities. You have several options to grant telegraf to run iptables: | ||
|
||
* Run telegraf as root. This is strongly discouraged. | ||
* Configure systemd to run telegraf with CAP_NET_ADMIN and CAP_NET_RAW. This is the simplest and recommended option. | ||
* Configure sudo to grant telegraf to run iptables. This is the most restrictive option, but require sudo setup. | ||
|
||
### Using systemd capabilities | ||
|
||
You may run `systemctl edit telegraf.service` and add the following: | ||
|
||
``` | ||
[Service] | ||
CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN | ||
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN | ||
``` | ||
|
||
Since telegraf will fork a process to run iptables, `AmbientCapabilities` is required to transmit the capabilities bounding set to the forked process. | ||
|
||
### Using sudo | ||
|
||
You may edit your sudo configuration with the following: | ||
|
||
```sudo | ||
telegraf ALL=(root) NOPASSWD: /usr/bin/iptables -nvL * | ||
``` | ||
|
||
### Configuration: | ||
|
||
```toml | ||
# use sudo to run iptables | ||
use_sudo = false | ||
# defines the table to monitor: | ||
table = "filter" | ||
# defines the chains to monitor: | ||
chains = [ "INPUT" ] | ||
``` | ||
|
||
### Measurements & Fields: | ||
|
||
|
||
- iptables | ||
- pkts (integer, count) | ||
- bytes (integer, bytes) | ||
|
||
### Tags: | ||
|
||
- All measurements have the following tags: | ||
- table | ||
- chain | ||
- ruleid | ||
|
||
The `ruleid` is the comment associated to the rule. | ||
|
||
### Example Output: | ||
|
||
``` | ||
$ iptables -nvL INPUT | ||
Chain INPUT (policy DROP 0 packets, 0 bytes) | ||
pkts bytes target prot opt in out source destination | ||
100 1024 ACCEPT tcp -- * * 192.168.0.0/24 0.0.0.0/0 tcp dpt:22 /* ssh */ | ||
42 2048 ACCEPT tcp -- * * 192.168.0.0/24 0.0.0.0/0 tcp dpt:80 /* httpd */ | ||
``` | ||
|
||
``` | ||
$ ./telegraf -config telegraf.conf -input-filter iptables -test | ||
iptables,table=filter,chain=INPUT,ruleid=ssh pkts=100i,bytes=1024i 1453831884664956455 | ||
iptables,table=filter,chain=INPUT,ruleid=httpd pkts=42i,bytes=2048i 1453831884664956455 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// +build linux | ||
|
||
package iptables | ||
|
||
import ( | ||
"errors" | ||
"os/exec" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/influxdata/telegraf" | ||
"github.com/influxdata/telegraf/plugins/inputs" | ||
) | ||
|
||
// Iptables is a telegraf plugin to gather packets and bytes throughput from Linux's iptables packet filter. | ||
type Iptables struct { | ||
UseSudo bool | ||
Table string | ||
Chains []string | ||
lister chainLister | ||
} | ||
|
||
// Description returns a short description of the plugin. | ||
func (ipt *Iptables) Description() string { | ||
return "Gather packets and bytes throughput from iptables" | ||
} | ||
|
||
// SampleConfig returns sample configuration options. | ||
func (ipt *Iptables) SampleConfig() string { | ||
return ` | ||
## iptables require root access on most systems. | ||
## Setting 'use_sudo' to true will make use of sudo to run iptables. | ||
## Users must configure sudo to allow telegraf user to run iptables with no password. | ||
## iptables can be restricted to only list command "iptables -nvL" | ||
use_sudo = false | ||
## defines the table to monitor: | ||
table = "filter" | ||
## defines the chains to monitor: | ||
chains = [ "INPUT" ] | ||
` | ||
} | ||
|
||
// Gather gathers iptables packets and bytes throughput from the configured tables and chains. | ||
func (ipt *Iptables) Gather(acc telegraf.Accumulator) error { | ||
if ipt.Table == "" || len(ipt.Chains) == 0 { | ||
return nil | ||
} | ||
// best effort : we continue through the chains even if an error is encountered, | ||
// but we keep track of the last error. | ||
var err error | ||
for _, chain := range ipt.Chains { | ||
data, e := ipt.lister(ipt.Table, chain) | ||
if e != nil { | ||
err = e | ||
continue | ||
} | ||
e = ipt.parseAndGather(data, acc) | ||
if e != nil { | ||
err = e | ||
continue | ||
} | ||
} | ||
return err | ||
} | ||
|
||
func (ipt *Iptables) chainList(table, chain string) (string, error) { | ||
iptablePath, err := exec.LookPath("iptables") | ||
if err != nil { | ||
return "", err | ||
} | ||
var args []string | ||
name := iptablePath | ||
if ipt.UseSudo { | ||
name = "sudo" | ||
args = append(args, iptablePath) | ||
} | ||
args = append(args, "-nvL", chain, "-t", table, "-x") | ||
c := exec.Command(name, args...) | ||
out, err := c.Output() | ||
return string(out), err | ||
} | ||
|
||
const measurement = "iptables" | ||
|
||
var errParse = errors.New("Cannot parse iptables list information") | ||
var chainNameRe = regexp.MustCompile(`^Chain\s+(\S+)`) | ||
var fieldsHeaderRe = regexp.MustCompile(`^\s*pkts\s+bytes\s+`) | ||
var valuesRe = regexp.MustCompile(`^\s*([0-9]+)\s+([0-9]+)\s+.*?(/\*\s(.*)\s\*/)?$`) | ||
|
||
func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error { | ||
lines := strings.Split(data, "\n") | ||
if len(lines) < 3 { | ||
return nil | ||
} | ||
mchain := chainNameRe.FindStringSubmatch(lines[0]) | ||
if mchain == nil { | ||
return errParse | ||
} | ||
if !fieldsHeaderRe.MatchString(lines[1]) { | ||
return errParse | ||
} | ||
for _, line := range lines[2:] { | ||
mv := valuesRe.FindAllStringSubmatch(line, -1) | ||
// best effort : if line does not match or rule is not commented forget about it | ||
if len(mv) == 0 || len(mv[0]) != 5 || mv[0][4] == "" { | ||
continue | ||
} | ||
tags := map[string]string{"table": ipt.Table, "chain": mchain[1], "ruleid": mv[0][4]} | ||
fields := make(map[string]interface{}) | ||
// since parse error is already catched by the regexp, | ||
// we never enter ther error case here => no error check (but still need a test to cover the case) | ||
fields["pkts"], _ = strconv.ParseUint(mv[0][1], 10, 64) | ||
fields["bytes"], _ = strconv.ParseUint(mv[0][2], 10, 64) | ||
acc.AddFields(measurement, fields, tags) | ||
} | ||
return nil | ||
} | ||
|
||
type chainLister func(table, chain string) (string, error) | ||
|
||
func init() { | ||
inputs.Add("iptables", func() telegraf.Input { | ||
ipt := new(Iptables) | ||
ipt.lister = ipt.chainList | ||
return ipt | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// +build !linux | ||
|
||
package iptables |
Oops, something went wrong.