netconfigd: export ipv4/ipv6 packet/bytes counters on :8066
This commit is contained in:
parent
6705108481
commit
bf2c12a69d
@ -3,10 +3,19 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/gokrazy/gokrazy"
|
||||||
|
"github.com/google/nftables"
|
||||||
|
"github.com/google/nftables/expr"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
|
"router7/internal/multilisten"
|
||||||
"router7/internal/netconfig"
|
"router7/internal/netconfig"
|
||||||
"router7/internal/teelogger"
|
"router7/internal/teelogger"
|
||||||
)
|
)
|
||||||
@ -17,7 +26,86 @@ var (
|
|||||||
linger = flag.Bool("linger", true, "linger around after applying the configuration (until killed)")
|
linger = flag.Bool("linger", true, "linger around after applying the configuration (until killed)")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var c nftables.Conn
|
||||||
|
for _, metric := range []struct {
|
||||||
|
name string
|
||||||
|
labels prometheus.Labels
|
||||||
|
table *nftables.Table
|
||||||
|
chain *nftables.Chain
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "filter_forward",
|
||||||
|
labels: prometheus.Labels{"family": "ipv4"},
|
||||||
|
table: &nftables.Table{Family: nftables.TableFamilyIPv4, Name: "filter"},
|
||||||
|
chain: &nftables.Chain{Name: "forward"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "filter_forward",
|
||||||
|
labels: prometheus.Labels{"family": "ipv6"},
|
||||||
|
table: &nftables.Table{Family: nftables.TableFamilyIPv6, Name: "filter"},
|
||||||
|
chain: &nftables.Chain{Name: "forward"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
metric := metric // copy
|
||||||
|
promauto.NewCounterFunc(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Subsystem: "nftables",
|
||||||
|
Name: metric.name + "_packets",
|
||||||
|
Help: "packet count",
|
||||||
|
ConstLabels: metric.labels,
|
||||||
|
},
|
||||||
|
func() float64 {
|
||||||
|
rules, err := c.GetRule(metric.table, metric.chain)
|
||||||
|
if err != nil ||
|
||||||
|
len(rules) != 1 ||
|
||||||
|
len(rules[0].Exprs) != 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if ce, ok := rules[0].Exprs[0].(*expr.Counter); ok {
|
||||||
|
return float64(ce.Packets)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
promauto.NewCounterFunc(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Subsystem: "nftables",
|
||||||
|
Name: metric.name + "_bytes",
|
||||||
|
Help: "bytes count",
|
||||||
|
ConstLabels: metric.labels,
|
||||||
|
},
|
||||||
|
func() float64 {
|
||||||
|
rules, err := c.GetRule(metric.table, metric.chain)
|
||||||
|
if err != nil ||
|
||||||
|
len(rules) != 1 ||
|
||||||
|
len(rules[0].Exprs) != 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if ce, ok := rules[0].Exprs[0].(*expr.Counter); ok {
|
||||||
|
return float64(ce.Bytes)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateListeners() error {
|
||||||
|
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if net1, err := multilisten.IPv6Net1("/perm"); err == nil {
|
||||||
|
hosts = append(hosts, net1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return multilisten.ListenAndServe(hosts, "8066", http.DefaultServeMux)
|
||||||
|
}
|
||||||
|
|
||||||
func logic() error {
|
func logic() error {
|
||||||
|
if *linger {
|
||||||
|
http.Handle("/metrics", promhttp.Handler())
|
||||||
|
updateListeners()
|
||||||
|
}
|
||||||
ch := make(chan os.Signal, 1)
|
ch := make(chan os.Signal, 1)
|
||||||
signal.Notify(ch, syscall.SIGUSR1)
|
signal.Notify(ch, syscall.SIGUSR1)
|
||||||
for {
|
for {
|
||||||
@ -36,6 +124,9 @@ func logic() error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
<-ch
|
<-ch
|
||||||
|
if err := updateListeners(); err != nil {
|
||||||
|
log.Printf("updateListeners: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/nftables/expr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const goldenInterfaces = `
|
const goldenInterfaces = `
|
||||||
@ -112,6 +113,8 @@ func TestNetconfig(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netconfig.DefaultCounter = expr.Counter{Packets: 23, Bytes: 42}
|
||||||
|
|
||||||
if err := netconfig.Apply(tmp, filepath.Join(tmp, "root")); err != nil {
|
if err := netconfig.Apply(tmp, filepath.Join(tmp, "root")); err != nil {
|
||||||
t.Fatalf("netconfig.Apply: %v", err)
|
t.Fatalf("netconfig.Apply: %v", err)
|
||||||
}
|
}
|
||||||
@ -227,6 +230,18 @@ func TestNetconfig(t *testing.T) {
|
|||||||
` oifname "uplink0" masquerade`,
|
` oifname "uplink0" masquerade`,
|
||||||
` }`,
|
` }`,
|
||||||
`}`,
|
`}`,
|
||||||
|
`table ip filter {`,
|
||||||
|
` chain forward {`,
|
||||||
|
` type filter hook forward priority 0; policy accept;`,
|
||||||
|
` counter packets 23 bytes 42`,
|
||||||
|
` }`,
|
||||||
|
`}`,
|
||||||
|
`table ip6 filter {`,
|
||||||
|
` chain forward {`,
|
||||||
|
` type filter hook forward priority 0; policy accept;`,
|
||||||
|
` counter packets 23 bytes 42`,
|
||||||
|
` }`,
|
||||||
|
`}`,
|
||||||
}
|
}
|
||||||
opts := []cmp.Option{
|
opts := []cmp.Option{
|
||||||
cmp.Transformer("formatting", func(line string) string {
|
cmp.Transformer("formatting", func(line string) string {
|
||||||
|
@ -454,6 +454,28 @@ func applyPortForwardings(dir string, c *nftables.Conn, nat *nftables.Table, pre
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultCounter is overridden while testing
|
||||||
|
var DefaultCounter expr.Counter
|
||||||
|
|
||||||
|
func getCounter(c *nftables.Conn, table *nftables.Table, chain *nftables.Chain) expr.Counter {
|
||||||
|
rules, err := c.GetRule(table, chain)
|
||||||
|
if err != nil {
|
||||||
|
return DefaultCounter
|
||||||
|
}
|
||||||
|
if got, want := len(rules), 1; got != want {
|
||||||
|
log.Printf("could not carry counter values: unexpected number of rules in table %v, chain %v: got %d, want %d", table.Name, chain.Name, got, want)
|
||||||
|
return DefaultCounter
|
||||||
|
}
|
||||||
|
if got, want := len(rules[0].Exprs), 1; got != want {
|
||||||
|
log.Printf("could not carry counter values: unexpected number of exprs in rule 0 in table %v, chain %v: got %d, want %d", table.Name, chain.Name, got, want)
|
||||||
|
return DefaultCounter
|
||||||
|
}
|
||||||
|
if ce, ok := rules[0].Exprs[0].(*expr.Counter); ok {
|
||||||
|
return *ce
|
||||||
|
}
|
||||||
|
return DefaultCounter
|
||||||
|
}
|
||||||
|
|
||||||
func applyFirewall(dir string) error {
|
func applyFirewall(dir string) error {
|
||||||
c := &nftables.Conn{}
|
c := &nftables.Conn{}
|
||||||
|
|
||||||
@ -501,6 +523,37 @@ func applyFirewall(dir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter4 := c.AddTable(&nftables.Table{
|
||||||
|
Family: nftables.TableFamilyIPv4,
|
||||||
|
Name: "filter",
|
||||||
|
})
|
||||||
|
|
||||||
|
filter6 := c.AddTable(&nftables.Table{
|
||||||
|
Family: nftables.TableFamilyIPv6,
|
||||||
|
Name: "filter",
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, filter := range []*nftables.Table{filter4, filter6} {
|
||||||
|
forward := c.AddChain(&nftables.Chain{
|
||||||
|
Name: "forward",
|
||||||
|
Hooknum: nftables.ChainHookForward,
|
||||||
|
Priority: nftables.ChainPriorityFilter,
|
||||||
|
Table: filter,
|
||||||
|
Type: nftables.ChainTypeFilter,
|
||||||
|
})
|
||||||
|
|
||||||
|
counter := getCounter(c, filter, forward)
|
||||||
|
|
||||||
|
c.AddRule(&nftables.Rule{
|
||||||
|
Table: filter,
|
||||||
|
Chain: forward,
|
||||||
|
Exprs: []expr.Any{
|
||||||
|
// [ counter pkts 23 bytes 42 ]
|
||||||
|
&counter,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return c.Flush()
|
return c.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user