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

feat(inputs.ipset): Add metric for number of entries and individual IPs #16124

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

verybadsoldier
Copy link

@verybadsoldier verybadsoldier commented Nov 1, 2024

Summary

Some automatic blacklist systems (like e.g. FireHOL) are feeding known malicious IP addresses regularly into ipsets to be blocked by firewalls (e.g. iptables/nftables). It would be useful to be able to track the number of entries of such ipsets over time.

As entries can use CIDR notation to target a range of IPs (e.g. 10.12.4.0/8) with a single ipset entry, it is also useful to see the number of actualy IPs affected by one ipset.

Checklist

  • No AI generated code was used in this PR

Related issues

resolves #16103

@telegraf-tiger telegraf-tiger bot added feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins labels Nov 1, 2024
Copy link
Member

@srebhan srebhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @verybadsoldier for your contribution. I do have some comments in the code...

Comment on lines 57 to 58
entryCounter := NewIpsetEntries(acc)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need to reinstantiate this in every gather cycle? How about doing it once in Init()?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok done

Comment on lines 13 to 21
type IpsetEntries struct {
acc telegraf.Accumulator
initizalized bool
setName string
numEntries int
numIps int
}

func NewIpsetEntries(acc telegraf.Accumulator) *IpsetEntries {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those two don't need to be exported as they are only used internally!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok done

plugins/inputs/ipset/ipset_entries.go Outdated Show resolved Hide resolved
plugins/inputs/ipset/ipset_entries.go Outdated Show resolved Hide resolved
plugins/inputs/ipset/ipset.go Outdated Show resolved Hide resolved
plugins/inputs/ipset/ipset_entries.go Outdated Show resolved Hide resolved
plugins/inputs/ipset/ipset_entries_test.go Outdated Show resolved Hide resolved
plugins/inputs/ipset/sample.conf Outdated Show resolved Hide resolved
@srebhan srebhan self-assigned this Nov 4, 2024
@telegraf-tiger
Copy link
Contributor

telegraf-tiger bot commented Nov 4, 2024

@verybadsoldier
Copy link
Author

Thanks for the review comments!

@verybadsoldier
Copy link
Author

Should I resolve the conversation I think I have solved or is that up to you?

Copy link
Member

@srebhan srebhan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update @verybadsoldier! A few more comments...

lister: setList,
Timeout: defaultTimeout,
lister: setList,
entriesParser: ipsetEntries{},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need in doing this initialization as entriesParser should already be initialized like this.

Comment on lines +56 to +78
func (counter *ipsetEntries) addLine(line string, acc telegraf.Accumulator) {
data := strings.Fields(line)
if len(data) < 3 {
acc.AddError(fmt.Errorf("error parsing line (expected at least 3 fields): %s", line))
return
}

operation := data[0]
if operation == "create" {
counter.commit(acc)
counter.initSet(data[1])
} else if operation == "add" {
counter.entries++

ip := data[2]
count, err := getCountInCidr(ip)
if err != nil {
acc.AddError(err)
return
}
counter.ips += count
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you simply return an error and add that error to the acc in the Gather caller?

Comment on lines +63 to +77
operation := data[0]
if operation == "create" {
counter.commit(acc)
counter.initSet(data[1])
} else if operation == "add" {
counter.entries++

ip := data[2]
count, err := getCountInCidr(ip)
if err != nil {
acc.AddError(err)
return
}
counter.ips += count
}
Copy link
Member

@srebhan srebhan Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
operation := data[0]
if operation == "create" {
counter.commit(acc)
counter.initSet(data[1])
} else if operation == "add" {
counter.entries++
ip := data[2]
count, err := getCountInCidr(ip)
if err != nil {
acc.AddError(err)
return
}
counter.ips += count
}
switch data[0] {
case "create":
counter.commit(acc)
counter.initizalized = true
counter.setName = data[1]
counter.entries = 0
counter.ips = 0
case "add":
counter.entries++
count, err := getCountInCidr(data[2])
if err != nil {
return err
}
counter.ips += count
}

Comment on lines +85 to +87
fields := make(map[string]interface{}, 3)
fields["entries"] = counter.entries
fields["ips"] = counter.ips
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why three? I only see two fields? Anyway I think this is easier

Suggested change
fields := make(map[string]interface{}, 3)
fields["entries"] = counter.entries
fields["ips"] = counter.ips
fields := map[string]interface{}{
"entries": counter.entries,
"ips": counter.ips,
}

Comment on lines +95 to +96
// reset counter and prepare for next usage
counter.reset()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// reset counter and prepare for next usage
counter.reset()
// reset counter and prepare for next usage
counter.initialized = false

@srebhan srebhan changed the title feat(inputs.ipset): add option to include number of entries and numbe… feat(inputs.ipset): Add metric for the tion to include number of entries and numbe of individual IPs Nov 12, 2024
@srebhan srebhan changed the title feat(inputs.ipset): Add metric for the tion to include number of entries and numbe of individual IPs feat(inputs.ipset): Add metric for the number of entries and individual IPs Nov 12, 2024
@srebhan srebhan changed the title feat(inputs.ipset): Add metric for the number of entries and individual IPs feat(inputs.ipset): Add metric for number of entries and individual IPs Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin plugin/input 1. Request for new input plugins 2. Issues/PRs that are related to input plugins
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[inputs.ipset] add metrics for number of entries in ipsets and number of individual IPs (resolve CIDR)
2 participants