2018-05-27 17:30:42 +02:00
|
|
|
// Binary netconfigd reads state from dhcp4, dhcp6, … and applies it.
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
2018-06-26 08:52:04 +02:00
|
|
|
"net"
|
2018-06-23 19:56:34 +02:00
|
|
|
"net/http"
|
2018-05-27 17:30:42 +02:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"syscall"
|
|
|
|
|
2018-06-23 19:56:34 +02:00
|
|
|
"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"
|
2018-05-27 17:30:42 +02:00
|
|
|
"router7/internal/netconfig"
|
2018-06-03 20:35:41 +02:00
|
|
|
"router7/internal/teelogger"
|
2018-05-27 17:30:42 +02:00
|
|
|
)
|
|
|
|
|
2018-06-03 20:35:41 +02:00
|
|
|
var log = teelogger.NewConsole()
|
|
|
|
|
2018-05-27 17:30:42 +02:00
|
|
|
var (
|
|
|
|
linger = flag.Bool("linger", true, "linger around after applying the configuration (until killed)")
|
|
|
|
)
|
|
|
|
|
2018-06-23 19:56:34 +02:00
|
|
|
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
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-26 08:52:04 +02:00
|
|
|
var httpListeners = multilisten.NewPool()
|
|
|
|
|
2018-06-23 19:56:34 +02:00
|
|
|
func updateListeners() error {
|
|
|
|
hosts, err := gokrazy.PrivateInterfaceAddrs()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if net1, err := multilisten.IPv6Net1("/perm"); err == nil {
|
|
|
|
hosts = append(hosts, net1)
|
|
|
|
}
|
|
|
|
|
2018-06-26 08:52:04 +02:00
|
|
|
httpListeners.ListenAndServe(hosts, func(host string) multilisten.Listener {
|
|
|
|
return &http.Server{Addr: net.JoinHostPort(host, "8066")}
|
|
|
|
})
|
|
|
|
return nil
|
2018-06-23 19:56:34 +02:00
|
|
|
}
|
|
|
|
|
2018-05-27 17:30:42 +02:00
|
|
|
func logic() error {
|
2018-06-23 19:56:34 +02:00
|
|
|
if *linger {
|
|
|
|
http.Handle("/metrics", promhttp.Handler())
|
2018-06-27 19:45:55 +02:00
|
|
|
if err := updateListeners(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-06-23 19:56:34 +02:00
|
|
|
}
|
2018-05-27 17:30:42 +02:00
|
|
|
ch := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(ch, syscall.SIGUSR1)
|
|
|
|
for {
|
2018-06-03 20:47:11 +02:00
|
|
|
err := netconfig.Apply("/perm/", "/")
|
2018-05-28 09:53:54 +02:00
|
|
|
// Notify gokrazy about new addresses (netconfig.Apply might have
|
|
|
|
// modified state before returning an error) so that listeners can be
|
|
|
|
// updated.
|
|
|
|
p, _ := os.FindProcess(1)
|
|
|
|
if err := p.Signal(syscall.SIGHUP); err != nil {
|
|
|
|
log.Printf("kill -HUP 1: %v", err)
|
|
|
|
}
|
|
|
|
if err != nil {
|
2018-05-27 17:30:42 +02:00
|
|
|
return err
|
|
|
|
}
|
2018-05-28 09:53:54 +02:00
|
|
|
if !*linger {
|
|
|
|
break
|
2018-05-27 17:30:42 +02:00
|
|
|
}
|
2018-05-28 09:53:54 +02:00
|
|
|
<-ch
|
2018-06-23 19:56:34 +02:00
|
|
|
if err := updateListeners(); err != nil {
|
|
|
|
log.Printf("updateListeners: %v", err)
|
|
|
|
}
|
2018-05-27 17:30:42 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
if err := logic(); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|