Merge remote-tracking branch 'github/master'
This commit is contained in:
commit
996061b126
12
.github/workflows/go.yml
vendored
12
.github/workflows/go.yml
vendored
@ -16,8 +16,8 @@ jobs:
|
|||||||
- name: Set up Go 1.x
|
- name: Set up Go 1.x
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
# Run on the latest minor release of Go 1.14:
|
# Run on the latest minor release of Go 1.18:
|
||||||
go-version: ^1.14
|
go-version: ^1.18
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
@ -51,8 +51,8 @@ jobs:
|
|||||||
- name: Set up Go 1.x
|
- name: Set up Go 1.x
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
# Run on the latest minor release of Go 1.14:
|
# Run on the latest minor release of Go 1.18:
|
||||||
go-version: ^1.14
|
go-version: ^1.18
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
@ -78,8 +78,8 @@ jobs:
|
|||||||
- name: Set up Go 1.x
|
- name: Set up Go 1.x
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
# Run on the latest minor release of Go 1.14:
|
# Run on the latest minor release of Go 1.18:
|
||||||
go-version: ^1.14
|
go-version: ^1.18
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
|
@ -97,6 +97,9 @@ var (
|
|||||||
}
|
}
|
||||||
return dur.Truncate(1 * time.Second).String()
|
return dur.Truncate(1 * time.Second).String()
|
||||||
},
|
},
|
||||||
|
"zero": func(t time.Time) bool {
|
||||||
|
return t.IsZero()
|
||||||
|
},
|
||||||
}).Parse(`<!DOCTYPE html>
|
}).Parse(`<!DOCTYPE html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
@ -156,8 +159,8 @@ form {
|
|||||||
<th>MAC address</th>
|
<th>MAC address</th>
|
||||||
<th>Vendor</th>
|
<th>Vendor</th>
|
||||||
<th>VendorIdentifier</th>
|
<th>VendorIdentifier</th>
|
||||||
<th>Start</th>
|
|
||||||
<th>Expiry</th>
|
<th>Expiry</th>
|
||||||
|
<th>Last ACK</th>
|
||||||
</tr>
|
</tr>
|
||||||
{{ range $idx, $l := . }}
|
{{ range $idx, $l := . }}
|
||||||
<tr>
|
<tr>
|
||||||
@ -174,18 +177,15 @@ form {
|
|||||||
<td class="hwaddr">{{$l.HardwareAddr}}</td>
|
<td class="hwaddr">{{$l.HardwareAddr}}</td>
|
||||||
<td>{{$l.Vendor}}</td>
|
<td>{{$l.Vendor}}</td>
|
||||||
<td>{{$l.VendorIdentifier}}</td>
|
<td>{{$l.VendorIdentifier}}</td>
|
||||||
<td>{{$l.Start}}</td>
|
|
||||||
<td title="{{ timefmt $l.Expiry }}">
|
<td title="{{ timefmt $l.Expiry }}">
|
||||||
{{ if $l.Expired }}
|
{{ if (not (zero $l.LastACK)) }}
|
||||||
{{ since $l.Expiry }}
|
{{ timefmt $l.LastACK }}
|
||||||
<span class="expired">expired</span>
|
{{ if $l.Active }}
|
||||||
{{ else }}
|
|
||||||
{{ if $l.Static }}
|
|
||||||
<span class="static">static</span>
|
|
||||||
{{ else }}
|
|
||||||
{{ timefmt $l.Expiry }}
|
|
||||||
<span class="active">active</span>
|
<span class="active">active</span>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ if $l.Expired }}
|
||||||
|
<span class="expired">expired</span>
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
@ -193,10 +193,16 @@ form {
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
<h1>Static Leases</h1>
|
||||||
<table cellpadding="0" cellspacing="0">
|
<table cellpadding="0" cellspacing="0">
|
||||||
{{ template "table" .StaticLeases }}
|
{{ template "table" .StaticLeases }}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Dynamic Leases</h1>
|
||||||
|
<table cellpadding="0" cellspacing="0">
|
||||||
{{ template "table" .DynamicLeases }}
|
{{ template "table" .DynamicLeases }}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`))
|
`))
|
||||||
@ -371,17 +377,20 @@ func newSrv(permDir string) (*srv, error) {
|
|||||||
Vendor string
|
Vendor string
|
||||||
Expired bool
|
Expired bool
|
||||||
Static bool
|
Static bool
|
||||||
|
Active bool
|
||||||
}
|
}
|
||||||
|
|
||||||
leasesMu.Lock()
|
leasesMu.Lock()
|
||||||
defer leasesMu.Unlock()
|
defer leasesMu.Unlock()
|
||||||
static := make([]tmplLease, 0, len(leases))
|
static := make([]tmplLease, 0, len(leases))
|
||||||
dynamic := make([]tmplLease, 0, len(leases))
|
dynamic := make([]tmplLease, 0, len(leases))
|
||||||
|
now := time.Now()
|
||||||
tl := func(l *dhcp4d.Lease) tmplLease {
|
tl := func(l *dhcp4d.Lease) tmplLease {
|
||||||
return tmplLease{
|
return tmplLease{
|
||||||
Lease: *l,
|
Lease: *l,
|
||||||
Vendor: ouiDB.Lookup(l.HardwareAddr[:8]),
|
Vendor: ouiDB.Lookup(l.HardwareAddr[:8]),
|
||||||
Expired: l.Expired(time.Now()),
|
Expired: l.Expired(now),
|
||||||
|
Active: l.Active(now),
|
||||||
Static: l.Expiry.IsZero(),
|
Static: l.Expiry.IsZero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,7 +453,7 @@ func newSrv(permDir string) (*srv, error) {
|
|||||||
Addr: latest.Addr.String(),
|
Addr: latest.Addr.String(),
|
||||||
HardwareAddr: latest.HardwareAddr,
|
HardwareAddr: latest.HardwareAddr,
|
||||||
Expiration: latest.Expiry.In(time.UTC),
|
Expiration: latest.Expiry.In(time.UTC),
|
||||||
Start: latest.Start.In(time.UTC),
|
Start: latest.LastACK.In(time.UTC),
|
||||||
VendorIdentifier: latest.VendorIdentifier,
|
VendorIdentifier: latest.VendorIdentifier,
|
||||||
}
|
}
|
||||||
leaseJSON, err := json.Marshal(leaseVal)
|
leaseJSON, err := json.Marshal(leaseVal)
|
||||||
|
@ -47,6 +47,8 @@ var (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var c nftables.Conn
|
var c nftables.Conn
|
||||||
|
filter4 := &nftables.Table{Family: nftables.TableFamilyIPv4, Name: "filter"}
|
||||||
|
filter6 := &nftables.Table{Family: nftables.TableFamilyIPv6, Name: "filter"}
|
||||||
for _, metric := range []struct {
|
for _, metric := range []struct {
|
||||||
name string
|
name string
|
||||||
labels prometheus.Labels
|
labels prometheus.Labels
|
||||||
@ -56,18 +58,34 @@ func init() {
|
|||||||
{
|
{
|
||||||
name: "filter_forward",
|
name: "filter_forward",
|
||||||
labels: prometheus.Labels{"family": "ipv4"},
|
labels: prometheus.Labels{"family": "ipv4"},
|
||||||
obj: &nftables.CounterObj{
|
obj: &nftables.CounterObj{Table: filter4, Name: "fwded"},
|
||||||
Table: &nftables.Table{Family: nftables.TableFamilyIPv4, Name: "filter"},
|
|
||||||
Name: "fwded",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "filter_forward",
|
name: "filter_forward",
|
||||||
labels: prometheus.Labels{"family": "ipv6"},
|
labels: prometheus.Labels{"family": "ipv6"},
|
||||||
obj: &nftables.CounterObj{
|
obj: &nftables.CounterObj{Table: filter6, Name: "fwded"},
|
||||||
Table: &nftables.Table{Family: nftables.TableFamilyIPv6, Name: "filter"},
|
|
||||||
Name: "fwded",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "filter_input",
|
||||||
|
labels: prometheus.Labels{"family": "ipv4"},
|
||||||
|
obj: &nftables.CounterObj{Table: filter4, Name: "inputc"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "filter_input",
|
||||||
|
labels: prometheus.Labels{"family": "ipv6"},
|
||||||
|
obj: &nftables.CounterObj{Table: filter6, Name: "inputc"},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "filter_output",
|
||||||
|
labels: prometheus.Labels{"family": "ipv4"},
|
||||||
|
obj: &nftables.CounterObj{Table: filter4, Name: "outputc"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "filter_output",
|
||||||
|
labels: prometheus.Labels{"family": "ipv6"},
|
||||||
|
obj: &nftables.CounterObj{Table: filter6, Name: "outputc"},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
metric := metric // copy
|
metric := metric // copy
|
||||||
@ -75,12 +93,11 @@ func init() {
|
|||||||
updateCounter := func() {
|
updateCounter := func() {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
objs, err := c.GetObjReset(metric.obj)
|
obj, err := c.ResetObject(metric.obj)
|
||||||
if err != nil ||
|
if err != nil {
|
||||||
len(objs) != 1 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if co, ok := objs[0].(*nftables.CounterObj); ok {
|
if co, ok := obj.(*nftables.CounterObj); ok {
|
||||||
metric.packets += co.Packets
|
metric.packets += co.Packets
|
||||||
metric.bytes += co.Bytes
|
metric.bytes += co.Bytes
|
||||||
}
|
}
|
||||||
|
6
go.mod
6
go.mod
@ -18,7 +18,7 @@ require (
|
|||||||
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
|
github.com/krolaw/dhcp4 v0.0.0-20190909130307-a50d88189771
|
||||||
github.com/libdns/cloudflare v0.1.0
|
github.com/libdns/cloudflare v0.1.0
|
||||||
github.com/libdns/libdns v0.2.0
|
github.com/libdns/libdns v0.2.0
|
||||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567
|
github.com/mdlayher/ndp v0.10.0
|
||||||
github.com/mdlayher/netlink v1.6.0 // indirect
|
github.com/mdlayher/netlink v1.6.0 // indirect
|
||||||
github.com/mdlayher/packet v1.0.0
|
github.com/mdlayher/packet v1.0.0
|
||||||
github.com/miekg/dns v1.1.42
|
github.com/miekg/dns v1.1.42
|
||||||
@ -30,9 +30,9 @@ require (
|
|||||||
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066
|
github.com/vishvananda/netlink v1.1.1-0.20200221165523-c79a4b7b4066
|
||||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
|
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||||
golang.zx2c4.com/wireguard v0.0.20201118 // indirect
|
golang.zx2c4.com/wireguard v0.0.20201118 // indirect
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5
|
||||||
|
14
go.sum
14
go.sum
@ -110,7 +110,6 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
|||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
@ -224,8 +223,8 @@ github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQob
|
|||||||
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
|
github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo=
|
||||||
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
|
github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0=
|
||||||
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
||||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567 h1:x+xs91ZJ+lr0C6sedWeREvck4uGCt+AA1kKXwsHB6jI=
|
github.com/mdlayher/ndp v0.10.0 h1:Zdwol2bq1EHY8xSnejIYkq6LEj7dLjLymJX0o/2tjGw=
|
||||||
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567/go.mod h1:32w/5dDZWVSEOxyniAgKK4d7dHTuO6TCxWmUznQe3f8=
|
github.com/mdlayher/ndp v0.10.0/go.mod h1:Uv6IWvgvqirNUu2N3ZXJEB86xu6foyUsG0NrClSSfek=
|
||||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||||
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||||
@ -438,7 +437,6 @@ golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191028085509-fe3aa8a45271/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
@ -450,8 +448,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||||
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -460,7 +459,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -494,7 +492,6 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200602100848-8d3cce7afc34/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -521,8 +518,9 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
|
||||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf h1:Fm4IcnUL803i92qDlmB0obyHmosDrxZWxJL3gIeNqOw=
|
||||||
|
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
|
@ -137,19 +137,20 @@ func goldenNftablesRules(additionalForwarding bool) string {
|
|||||||
add := ""
|
add := ""
|
||||||
if additionalForwarding {
|
if additionalForwarding {
|
||||||
add = `
|
add = `
|
||||||
iifname "uplink0" tcp dport 8045 dnat to 192.168.42.22:8045`
|
ip daddr != 127.0.0.0/8 ip daddr != 10.0.0.0/24 fib daddr type 2 tcp dport 8045 dnat to 192.168.42.22:8045`
|
||||||
}
|
}
|
||||||
return `table ip nat {
|
return `table ip nat {
|
||||||
chain prerouting {
|
chain prerouting {
|
||||||
type nat hook prerouting priority 0; policy accept;
|
type nat hook prerouting priority 0; policy accept;
|
||||||
iifname "uplink0" tcp dport 8080 dnat to 192.168.42.23:9999` + add + `
|
ip daddr != 127.0.0.0/8 ip daddr != 10.0.0.0/24 fib daddr type 2 tcp dport 8080 dnat to 192.168.42.23:9999` + add + `
|
||||||
iifname "uplink0" tcp dport 8040-8060 dnat to 192.168.42.99:8040-8060
|
ip daddr != 127.0.0.0/8 ip daddr != 10.0.0.0/24 fib daddr type 2 tcp dport 8040-8060 dnat to 192.168.42.99:8040-8060
|
||||||
iifname "uplink0" udp dport 53 dnat to 192.168.42.99:53
|
ip daddr != 127.0.0.0/8 ip daddr != 10.0.0.0/24 fib daddr type 2 udp dport 53 dnat to 192.168.42.99:53
|
||||||
}
|
}
|
||||||
|
|
||||||
chain postrouting {
|
chain postrouting {
|
||||||
type nat hook postrouting priority 100; policy accept;
|
type nat hook postrouting priority 100; policy accept;
|
||||||
oifname "uplink0" masquerade
|
oifname "uplink0" masquerade
|
||||||
|
iifname "lan0" oifname "lan0" ct status 0x20 masquerade
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table ip filter {
|
table ip filter {
|
||||||
@ -157,14 +158,11 @@ table ip filter {
|
|||||||
packets 23 bytes 42
|
packets 23 bytes 42
|
||||||
}
|
}
|
||||||
|
|
||||||
chain forward {
|
counter inputc {
|
||||||
type filter hook forward priority 0; policy accept;
|
packets 23 bytes 42
|
||||||
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
|
||||||
counter name "fwded"
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
table ip6 filter {
|
counter outputc {
|
||||||
counter fwded {
|
|
||||||
packets 23 bytes 42
|
packets 23 bytes 42
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +171,45 @@ table ip6 filter {
|
|||||||
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
||||||
counter name "fwded"
|
counter name "fwded"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy accept;
|
||||||
|
counter name "inputc"
|
||||||
|
}
|
||||||
|
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority 0; policy accept;
|
||||||
|
counter name "outputc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table ip6 filter {
|
||||||
|
counter fwded {
|
||||||
|
packets 23 bytes 42
|
||||||
|
}
|
||||||
|
|
||||||
|
counter inputc {
|
||||||
|
packets 23 bytes 42
|
||||||
|
}
|
||||||
|
|
||||||
|
counter outputc {
|
||||||
|
packets 23 bytes 42
|
||||||
|
}
|
||||||
|
|
||||||
|
chain forward {
|
||||||
|
type filter hook forward priority 0; policy accept;
|
||||||
|
oifname "uplink0" tcp flags 0x2 tcp option maxseg size set rt mtu
|
||||||
|
counter name "fwded"
|
||||||
|
}
|
||||||
|
|
||||||
|
chain input {
|
||||||
|
type filter hook input priority 0; policy accept;
|
||||||
|
counter name "inputc"
|
||||||
|
}
|
||||||
|
|
||||||
|
chain output {
|
||||||
|
type filter hook output priority 0; policy accept;
|
||||||
|
counter name "outputc"
|
||||||
|
}
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,14 +43,18 @@ type Lease struct {
|
|||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
HostnameOverride string `json:"hostname_override"`
|
HostnameOverride string `json:"hostname_override"`
|
||||||
Expiry time.Time `json:"expiry"`
|
Expiry time.Time `json:"expiry"`
|
||||||
Start time.Time `json:"start"`
|
|
||||||
VendorIdentifier string `json:"vendor"`
|
VendorIdentifier string `json:"vendor"`
|
||||||
|
LastACK time.Time `json:"last_ack"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Lease) Expired(at time.Time) bool {
|
func (l *Lease) Expired(at time.Time) bool {
|
||||||
return !l.Expiry.IsZero() && at.After(l.Expiry)
|
return !l.Expiry.IsZero() && at.After(l.Expiry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Lease) Active(at time.Time) bool {
|
||||||
|
return !l.LastACK.IsZero() && at.Before(l.LastACK.Add(leasePeriod))
|
||||||
|
}
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
serverIP net.IP
|
serverIP net.IP
|
||||||
start net.IP // first IP address to hand out
|
start net.IP // first IP address to hand out
|
||||||
@ -113,16 +117,18 @@ func NewHandler(dir string, iface *net.Interface, ifaceName string, conn net.Pac
|
|||||||
serverIP: serverIP,
|
serverIP: serverIP,
|
||||||
start: start,
|
start: start,
|
||||||
leaseRange: 230,
|
leaseRange: 230,
|
||||||
// Apple recommends a DHCP lease time of 1 hour in
|
LeasePeriod: leasePeriod,
|
||||||
// https://support.apple.com/de-ch/HT202068,
|
|
||||||
// so if 20 minutes ever causes any trouble,
|
|
||||||
// we should try increasing it to 1 hour.
|
|
||||||
LeasePeriod: 20 * time.Minute,
|
|
||||||
options: options,
|
options: options,
|
||||||
timeNow: time.Now,
|
timeNow: time.Now,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apple recommends a DHCP lease time of 1 hour in
|
||||||
|
// https://support.apple.com/de-ch/HT202068,
|
||||||
|
// so if 20 minutes ever causes any trouble,
|
||||||
|
// we should try increasing it to 1 hour.
|
||||||
|
const leasePeriod = 20 * time.Minute
|
||||||
|
|
||||||
// SetLeases overwrites the leases database with the specified leases, typically
|
// SetLeases overwrites the leases database with the specified leases, typically
|
||||||
// loaded from persistent storage. There is no locking, so SetLeases must be
|
// loaded from persistent storage. There is no locking, so SetLeases must be
|
||||||
// called before Serve.
|
// called before Serve.
|
||||||
@ -132,6 +138,9 @@ func (h *Handler) SetLeases(leases []*Lease) {
|
|||||||
h.leasesHW = make(map[string]int)
|
h.leasesHW = make(map[string]int)
|
||||||
h.leasesIP = make(map[int]*Lease)
|
h.leasesIP = make(map[int]*Lease)
|
||||||
for _, l := range leases {
|
for _, l := range leases {
|
||||||
|
if l.LastACK.IsZero() {
|
||||||
|
l.LastACK = l.Expiry
|
||||||
|
}
|
||||||
h.leasesHW[l.HardwareAddr] = l.Num
|
h.leasesHW[l.HardwareAddr] = l.Num
|
||||||
h.leasesIP[l.Num] = l
|
h.leasesIP[l.Num] = l
|
||||||
}
|
}
|
||||||
@ -344,8 +353,8 @@ func (h *Handler) serveDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
|
|||||||
HardwareAddr: hwAddr,
|
HardwareAddr: hwAddr,
|
||||||
Expiry: now.Add(h.leasePeriodForDevice(hwAddr)),
|
Expiry: now.Add(h.leasePeriodForDevice(hwAddr)),
|
||||||
Hostname: string(options[dhcp4.OptionHostName]),
|
Hostname: string(options[dhcp4.OptionHostName]),
|
||||||
Start: now,
|
|
||||||
VendorIdentifier: string(bytes.ToValidUTF8(bytes.ReplaceAll(options[dhcp4.OptionVendorClassIdentifier], []byte{0}, []byte{}), []byte{})),
|
VendorIdentifier: string(bytes.ToValidUTF8(bytes.ReplaceAll(options[dhcp4.OptionVendorClassIdentifier], []byte{0}, []byte{}), []byte{})),
|
||||||
|
LastACK: h.timeNow(),
|
||||||
}
|
}
|
||||||
copy(lease.Addr, reqIP.To4())
|
copy(lease.Addr, reqIP.To4())
|
||||||
|
|
||||||
|
@ -412,6 +412,73 @@ func nfifname(n string) []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// matchUplinkIP is conceptually equivalent to "ip daddr <uplink0-ip>", but
|
||||||
|
// without actually using the IP address of the uplink0 interface (which would
|
||||||
|
// mean that rules need to change when the IP address changes).
|
||||||
|
//
|
||||||
|
// Instead, it uses “fib daddr type local” to match all locally-configured IP
|
||||||
|
// addresses and then excludes the loopback and LAN IP addresses.
|
||||||
|
func matchUplinkIP() []expr.Any {
|
||||||
|
return []expr.Any{
|
||||||
|
// [ payload load 4b @ network header + 16 => reg 1 ]
|
||||||
|
&expr.Payload{
|
||||||
|
DestRegister: 1,
|
||||||
|
Base: expr.PayloadBaseNetworkHeader,
|
||||||
|
Offset: 16, // TODO
|
||||||
|
Len: 4, // TODO
|
||||||
|
},
|
||||||
|
// [ bitwise reg 1 = (reg=1 & 0x000000ff ) ^ 0x00000000 ]
|
||||||
|
&expr.Bitwise{
|
||||||
|
DestRegister: 1,
|
||||||
|
SourceRegister: 1,
|
||||||
|
Len: 4,
|
||||||
|
Mask: []byte{0xff, 0x00, 0x00, 0x00}, // 255.0.0.0, i.e. /8
|
||||||
|
Xor: []byte{0x00, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
// [ cmp neq reg 1 0x0000007f ]
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpNeq,
|
||||||
|
Register: 1,
|
||||||
|
Data: []byte{0x7f, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
|
||||||
|
// [ payload load 4b @ network header + 16 => reg 1 ]
|
||||||
|
&expr.Payload{
|
||||||
|
DestRegister: 1,
|
||||||
|
Base: expr.PayloadBaseNetworkHeader,
|
||||||
|
Offset: 16, // TODO
|
||||||
|
Len: 4, // TODO
|
||||||
|
},
|
||||||
|
// [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ]
|
||||||
|
&expr.Bitwise{
|
||||||
|
DestRegister: 1,
|
||||||
|
SourceRegister: 1,
|
||||||
|
Len: 4,
|
||||||
|
Mask: []byte{0xff, 0xff, 0xff, 0x00}, // 255.255.255.0, i.e. /24
|
||||||
|
Xor: []byte{0x00, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
// [ cmp neq reg 1 0x0000000a ]
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpNeq,
|
||||||
|
Register: 1,
|
||||||
|
Data: []byte{0x0a, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
|
||||||
|
// [ fib daddr type => reg 1 ]
|
||||||
|
&expr.Fib{
|
||||||
|
Register: 1,
|
||||||
|
FlagDADDR: true,
|
||||||
|
ResultADDRTYPE: true,
|
||||||
|
},
|
||||||
|
// [ cmp eq reg 1 0x00000002 ]
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: []byte{0x02, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest net.IP, dportMin, dportMax uint16) []expr.Any {
|
func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest net.IP, dportMin, dportMax uint16) []expr.Any {
|
||||||
var cmp []expr.Any
|
var cmp []expr.Any
|
||||||
if portMin == portMax {
|
if portMin == portMax {
|
||||||
@ -439,16 +506,7 @@ func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest n
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ex := []expr.Any{
|
ex := append(matchUplinkIP(),
|
||||||
// [ meta load iifname => reg 1 ]
|
|
||||||
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
|
|
||||||
// [ cmp eq reg 1 0x696c7075 0x00306b6e 0x00000000 0x00000000 ]
|
|
||||||
&expr.Cmp{
|
|
||||||
Op: expr.CmpOpEq,
|
|
||||||
Register: 1,
|
|
||||||
Data: nfifname(ifname),
|
|
||||||
},
|
|
||||||
|
|
||||||
// [ meta load l4proto => reg 1 ]
|
// [ meta load l4proto => reg 1 ]
|
||||||
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
|
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
|
||||||
// [ cmp eq reg 1 0x00000006 ]
|
// [ cmp eq reg 1 0x00000006 ]
|
||||||
@ -464,8 +522,7 @@ func portForwardExpr(ifname string, proto uint8, portMin, portMax uint16, dest n
|
|||||||
Base: expr.PayloadBaseTransportHeader,
|
Base: expr.PayloadBaseTransportHeader,
|
||||||
Offset: 2, // TODO
|
Offset: 2, // TODO
|
||||||
Len: 2, // TODO
|
Len: 2, // TODO
|
||||||
},
|
})
|
||||||
}
|
|
||||||
ex = append(ex, cmp...)
|
ex = append(ex, cmp...)
|
||||||
ex = append(ex,
|
ex = append(ex,
|
||||||
// [ immediate reg 1 0x0217a8c0 ]
|
// [ immediate reg 1 0x0217a8c0 ]
|
||||||
@ -594,35 +651,13 @@ func applyPortForwardings(dir, ifname string, c *nftables.Conn, nat *nftables.Ta
|
|||||||
var DefaultCounterObj = &nftables.CounterObj{}
|
var DefaultCounterObj = &nftables.CounterObj{}
|
||||||
|
|
||||||
func getCounterObj(c *nftables.Conn, o *nftables.CounterObj) *nftables.CounterObj {
|
func getCounterObj(c *nftables.Conn, o *nftables.CounterObj) *nftables.CounterObj {
|
||||||
objs, err := c.GetObj(o)
|
obj, err := c.GetObject(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
o.Bytes = DefaultCounterObj.Bytes
|
o.Bytes = DefaultCounterObj.Bytes
|
||||||
o.Packets = DefaultCounterObj.Packets
|
o.Packets = DefaultCounterObj.Packets
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
{
|
if co, ok := obj.(*nftables.CounterObj); ok {
|
||||||
// TODO: remove this workaround once travis has workers with a newer kernel
|
|
||||||
// than its current Ubuntu trusty kernel (Linux 4.4.0):
|
|
||||||
var filtered []nftables.Obj
|
|
||||||
for _, obj := range objs {
|
|
||||||
co, ok := obj.(*nftables.CounterObj)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if co.Table.Name != o.Table.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
filtered = append(filtered, obj)
|
|
||||||
}
|
|
||||||
objs = filtered
|
|
||||||
}
|
|
||||||
if got, want := len(objs), 1; got != want {
|
|
||||||
log.Printf("could not carry counter values: unexpected number of objects in table %v: got %d, want %d", o.Table.Name, got, want)
|
|
||||||
o.Bytes = DefaultCounterObj.Bytes
|
|
||||||
o.Packets = DefaultCounterObj.Packets
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
if co, ok := objs[0].(*nftables.CounterObj); ok {
|
|
||||||
return co
|
return co
|
||||||
}
|
}
|
||||||
o.Bytes = DefaultCounterObj.Bytes
|
o.Bytes = DefaultCounterObj.Bytes
|
||||||
@ -630,6 +665,52 @@ func getCounterObj(c *nftables.Conn, o *nftables.CounterObj) *nftables.CounterOb
|
|||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hairpinDNAT() []expr.Any {
|
||||||
|
return []expr.Any{
|
||||||
|
// [ meta load oifname => reg 1 ]
|
||||||
|
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
|
||||||
|
// [ cmp eq reg 1 0x306e616c 0x00000000 0x00000000 0x00000000 ]
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: nfifname("lan0"),
|
||||||
|
},
|
||||||
|
|
||||||
|
// [ meta load oifname => reg 1 ]
|
||||||
|
&expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
|
||||||
|
// [ cmp eq reg 1 0x306e616c 0x00000000 0x00000000 0x00000000 ]
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: nfifname("lan0"),
|
||||||
|
},
|
||||||
|
|
||||||
|
// [ ct load status => reg 1 ]
|
||||||
|
&expr.Ct{
|
||||||
|
Register: 1,
|
||||||
|
SourceRegister: false,
|
||||||
|
Key: expr.CtKeySTATUS,
|
||||||
|
},
|
||||||
|
// [ bitwise reg 1 = (reg=1 & 0x00000020 ) ^ 0x00000000 ]
|
||||||
|
&expr.Bitwise{
|
||||||
|
DestRegister: 1,
|
||||||
|
SourceRegister: 1,
|
||||||
|
Len: 4,
|
||||||
|
Mask: []byte{0x20, 0x00, 0x00, 0x00},
|
||||||
|
Xor: []byte{0x00, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
|
||||||
|
// [ cmp neq reg 1 0x00000000 ]
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpNeq,
|
||||||
|
Register: 1,
|
||||||
|
Data: []byte{0x00, 0x00, 0x00, 0x00},
|
||||||
|
},
|
||||||
|
// [ masq ]
|
||||||
|
&expr.Masq{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func applyFirewall(dir, ifname string) error {
|
func applyFirewall(dir, ifname string) error {
|
||||||
c := &nftables.Conn{}
|
c := &nftables.Conn{}
|
||||||
|
|
||||||
@ -673,6 +754,12 @@ func applyFirewall(dir, ifname string) error {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
c.AddRule(&nftables.Rule{
|
||||||
|
Table: nat,
|
||||||
|
Chain: postrouting,
|
||||||
|
Exprs: hairpinDNAT(),
|
||||||
|
})
|
||||||
|
|
||||||
if err := applyPortForwardings(dir, ifname, c, nat, prerouting); err != nil {
|
if err := applyPortForwardings(dir, ifname, c, nat, prerouting); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -782,6 +869,56 @@ func applyFirewall(dir, ifname string) error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
input := c.AddChain(&nftables.Chain{
|
||||||
|
Name: "input",
|
||||||
|
Hooknum: nftables.ChainHookInput,
|
||||||
|
Priority: nftables.ChainPriorityFilter,
|
||||||
|
Table: filter,
|
||||||
|
Type: nftables.ChainTypeFilter,
|
||||||
|
})
|
||||||
|
|
||||||
|
counterObj = getCounterObj(c, &nftables.CounterObj{
|
||||||
|
Table: filter,
|
||||||
|
Name: "inputc",
|
||||||
|
})
|
||||||
|
counter = c.AddObj(counterObj).(*nftables.CounterObj)
|
||||||
|
c.AddRule(&nftables.Rule{
|
||||||
|
Table: filter,
|
||||||
|
Chain: input,
|
||||||
|
Exprs: []expr.Any{
|
||||||
|
// [ counter name input ]
|
||||||
|
&expr.Objref{
|
||||||
|
Type: NFT_OBJECT_COUNTER,
|
||||||
|
Name: counter.Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
output := c.AddChain(&nftables.Chain{
|
||||||
|
Name: "output",
|
||||||
|
Hooknum: nftables.ChainHookOutput,
|
||||||
|
Priority: nftables.ChainPriorityFilter,
|
||||||
|
Table: filter,
|
||||||
|
Type: nftables.ChainTypeFilter,
|
||||||
|
})
|
||||||
|
|
||||||
|
counterObj = getCounterObj(c, &nftables.CounterObj{
|
||||||
|
Table: filter,
|
||||||
|
Name: "outputc",
|
||||||
|
})
|
||||||
|
counter = c.AddObj(counterObj).(*nftables.CounterObj)
|
||||||
|
c.AddRule(&nftables.Rule{
|
||||||
|
Table: filter,
|
||||||
|
Chain: output,
|
||||||
|
Exprs: []expr.Any{
|
||||||
|
// [ counter name output ]
|
||||||
|
&expr.Objref{
|
||||||
|
Type: NFT_OBJECT_COUNTER,
|
||||||
|
Name: counter.Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Flush()
|
return c.Flush()
|
||||||
|
@ -18,6 +18,7 @@ package radvd
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -144,21 +145,21 @@ func (s *Server) sendAdvertisement(addr net.Addr) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var linkLocal net.IP
|
var linkLocal netip.Addr
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
ipnet, ok := addr.(*net.IPNet)
|
ipnet, ok := addr.(*net.IPNet)
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ipv6LinkLocal.Contains(ipnet.IP) {
|
if ipv6LinkLocal.Contains(ipnet.IP) {
|
||||||
linkLocal = ipnet.IP
|
linkLocal, _ = netip.AddrFromSlice(ipnet.IP)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !linkLocal.Equal(net.IPv6zero) {
|
if linkLocal.IsValid() && !linkLocal.IsUnspecified() {
|
||||||
options = append(options, &ndp.RecursiveDNSServer{
|
options = append(options, &ndp.RecursiveDNSServer{
|
||||||
Lifetime: 30 * time.Minute,
|
Lifetime: 30 * time.Minute,
|
||||||
Servers: []net.IP{linkLocal},
|
Servers: []netip.Addr{linkLocal},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,13 +171,14 @@ func (s *Server) sendAdvertisement(addr net.Addr) error {
|
|||||||
ones = 64
|
ones = 64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr, _ := netip.AddrFromSlice(prefix.IP)
|
||||||
options = append(options, &ndp.PrefixInformation{
|
options = append(options, &ndp.PrefixInformation{
|
||||||
PrefixLength: uint8(ones),
|
PrefixLength: uint8(ones),
|
||||||
OnLink: true,
|
OnLink: true,
|
||||||
AutonomousAddressConfiguration: true,
|
AutonomousAddressConfiguration: true,
|
||||||
ValidLifetime: 2 * time.Hour,
|
ValidLifetime: 2 * time.Hour,
|
||||||
PreferredLifetime: 30 * time.Minute,
|
PreferredLifetime: 30 * time.Minute,
|
||||||
Prefix: prefix.IP,
|
Prefix: addr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,8 +107,6 @@ Example:
|
|||||||
Schema: see [`portForwardings`](
|
Schema: see [`portForwardings`](
|
||||||
https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L431)
|
https://github.com/rtr7/router7/blob/f86e20be5305fc0e7e77421e0f2abde98a84f2a7/internal/netconfig/netconfig.go#L431)
|
||||||
|
|
||||||
Please be aware that Hairpinning is currently not supported (see issue [#53 Support for Hairpinning](https://github.com/rtr7/router7/issues/53]))
|
|
||||||
|
|
||||||
## Updates
|
## Updates
|
||||||
|
|
||||||
Run e.g. `rtr7-safe-update -updates_dir=$HOME/router7/updates` to:
|
Run e.g. `rtr7-safe-update -updates_dir=$HOME/router7/updates` to:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user