Compare commits
3 Commits
f9618226fd
...
426bd5a659
Author | SHA1 | Date | |
---|---|---|---|
426bd5a659 | |||
5ff8521bf4 | |||
0faa8ec86a |
165
addr-map.go
165
addr-map.go
@ -1,43 +1,148 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/cespare/xxhash/v2"
|
"github.com/cespare/xxhash/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: write more convenient version
|
const (
|
||||||
func addrMap(srcIp net.IP, dstCidr *net.IPNet) net.IP {
|
addrMapHouseKeepInterval = time.Second / 2
|
||||||
addrlen := len(srcIp)
|
)
|
||||||
if addrlen != len(dstCidr.IP) {
|
|
||||||
log.Fatalf("addrMap(): src/dst size mismatch: %v vs %v", len(srcIp), len(dstCidr.IP))
|
|
||||||
}
|
|
||||||
|
|
||||||
var addr net.IP = make([]byte, addrlen)
|
var (
|
||||||
|
addr4, addr6 sync.Map
|
||||||
|
)
|
||||||
|
|
||||||
hsum := xxhash.Sum64(srcIp)
|
type AddrMap struct {
|
||||||
bsum := binary.NativeEndian.AppendUint64([]byte{}, hsum)
|
SrcAddr net.IP
|
||||||
blen := len(bsum)
|
DstAddr net.IP
|
||||||
if addrlen > blen {
|
Ttl uint32
|
||||||
// extend bsum
|
Created time.Time
|
||||||
tmp := append(make([]byte, addrlen-blen), bsum...)
|
}
|
||||||
bsum = tmp
|
|
||||||
}
|
func (a *AddrMap) GetTtl() int32 {
|
||||||
if addrlen < blen {
|
x := math.Trunc(time.Since(a.Created).Round(addrMapHouseKeepInterval).Seconds())
|
||||||
// trim bsum
|
return int32(a.Ttl) - int32(x)
|
||||||
bsum = bsum[:addrlen]
|
}
|
||||||
}
|
|
||||||
|
func setupAddrMapHousekeeping() {
|
||||||
// apply inverted mask to bsum and sum with addr
|
go func() {
|
||||||
for i := range addrlen / 4 {
|
for {
|
||||||
a := binary.NativeEndian.Uint32(dstCidr.IP[i*4:])
|
time.Sleep(addrMapHouseKeepInterval)
|
||||||
b := binary.NativeEndian.Uint32(bsum[i*4:])
|
addr4.Range(func(key, value any) bool {
|
||||||
m := binary.NativeEndian.Uint32(dstCidr.Mask[i*4:])
|
a, ok := value.(AddrMap)
|
||||||
a += (b & ^m)
|
if ok {
|
||||||
binary.NativeEndian.PutUint32(addr[i*4:], a)
|
if a.GetTtl() > 1 {
|
||||||
}
|
return true
|
||||||
|
}
|
||||||
return addr
|
}
|
||||||
|
// delete if value is bogus or if ttl is less than second
|
||||||
|
addr4.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
time.Sleep(addrMapHouseKeepInterval)
|
||||||
|
addr6.Range(func(key, value any) bool {
|
||||||
|
a, ok := value.(AddrMap)
|
||||||
|
if ok {
|
||||||
|
if a.GetTtl() > 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// delete if value is bogus or if ttl is less than second
|
||||||
|
addr6.Delete(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func addrMapGet(srcIp net.IP, dstCidr *net.IPNet, ttl uint32) net.IP {
|
||||||
|
addrlen := len(srcIp)
|
||||||
|
switch addrlen {
|
||||||
|
case net.IPv4len, net.IPv6len:
|
||||||
|
default:
|
||||||
|
log.Fatalf("addrMapGet(): src size mismatch: %v", addrlen)
|
||||||
|
}
|
||||||
|
if addrlen != len(dstCidr.IP) {
|
||||||
|
log.Fatalf("addrMapGet(): src/dst size mismatch: %v vs %v", addrlen, len(dstCidr.IP))
|
||||||
|
}
|
||||||
|
if addrlen != len(dstCidr.Mask) {
|
||||||
|
log.Fatalf("addrMapGet(): src/dst size mismatch: %v vs %v", addrlen, len(dstCidr.IP))
|
||||||
|
}
|
||||||
|
|
||||||
|
var curr AddrMap
|
||||||
|
curr.SrcAddr = make([]byte, addrlen)
|
||||||
|
curr.DstAddr = make([]byte, addrlen)
|
||||||
|
copy(curr.DstAddr, srcIp)
|
||||||
|
curr.Ttl = ttl
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err := rand.Read(curr.SrcAddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("rand.Read(): error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust random bytes to dstCidr
|
||||||
|
for i := range addrlen / 4 {
|
||||||
|
a := binary.NativeEndian.Uint32(dstCidr.IP[i*4:])
|
||||||
|
b := binary.NativeEndian.Uint32(curr.SrcAddr[i*4:])
|
||||||
|
m := binary.NativeEndian.Uint32(dstCidr.Mask[i*4:])
|
||||||
|
a += (b & ^m)
|
||||||
|
binary.NativeEndian.PutUint32(curr.SrcAddr[i*4:], a)
|
||||||
|
}
|
||||||
|
hsum := xxhash.Sum64(curr.SrcAddr)
|
||||||
|
|
||||||
|
curr.Created = time.Now()
|
||||||
|
|
||||||
|
var xprev any
|
||||||
|
var loaded bool
|
||||||
|
switch addrlen {
|
||||||
|
case net.IPv4len:
|
||||||
|
xprev, loaded = addr4.LoadOrStore(hsum, curr)
|
||||||
|
case net.IPv6len:
|
||||||
|
xprev, loaded = addr6.LoadOrStore(hsum, curr)
|
||||||
|
}
|
||||||
|
if !loaded {
|
||||||
|
// early return
|
||||||
|
return curr.SrcAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
prev, ok := xprev.(AddrMap)
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("addrMapGet(): wrong value type from sync.Map")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !net.IP.Equal(curr.SrcAddr, prev.SrcAddr) {
|
||||||
|
// generate next random address
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !net.IP.Equal(curr.DstAddr, prev.DstAddr) {
|
||||||
|
// generate next random address
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev.GetTtl() < int32(curr.Ttl) {
|
||||||
|
switch addrlen {
|
||||||
|
case net.IPv4len:
|
||||||
|
addr4.Store(hsum, curr)
|
||||||
|
case net.IPv6len:
|
||||||
|
addr6.Store(hsum, curr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return curr.SrcAddr
|
||||||
}
|
}
|
||||||
|
6
cfg.go
6
cfg.go
@ -14,14 +14,14 @@ const (
|
|||||||
|
|
||||||
cfgResolverEndpoint = "127.1.0.1:53"
|
cfgResolverEndpoint = "127.1.0.1:53"
|
||||||
cfgResolverProto = "tcp"
|
cfgResolverProto = "tcp"
|
||||||
cfgResolverTimeout = 2500 * time.Millisecond
|
cfgResolverTimeout = 2000 * time.Millisecond
|
||||||
|
|
||||||
cfgNftTable = "uni"
|
cfgNftTable = "uni"
|
||||||
cfgNftTableFamily = nft.TableFamilyINet
|
cfgNftTableFamily = nft.TableFamilyINet
|
||||||
cfgNftMapV4 = "tele4"
|
cfgNftMapV4 = "tele4"
|
||||||
cfgNftMapV6 = "tele6"
|
cfgNftMapV6 = "tele6"
|
||||||
cfgNftCidrV4 = "251.0.0.0/8"
|
cfgNftCidrV4 = "198.18.0.0/15"
|
||||||
cfgNftCidrV6 = "2001:db8:11::/48"
|
cfgNftCidrV6 = "2001:db8:11::/80"
|
||||||
|
|
||||||
cfgSoaNs = "gw.vpn."
|
cfgSoaNs = "gw.vpn."
|
||||||
cfgSoaMbox = "dns.gw.vpn."
|
cfgSoaMbox = "dns.gw.vpn."
|
||||||
|
@ -140,18 +140,19 @@ func dnsRemap(qname string, qtype uint16, orig *dns.Msg) ([]PowerDnsAnswer, erro
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK: clip ttl
|
||||||
|
r.Ttl = dnsClipTtl(r.Ttl)
|
||||||
|
|
||||||
var srcAddr net.IP = make([]byte, r.AddrLen)
|
var srcAddr net.IP = make([]byte, r.AddrLen)
|
||||||
copy(srcAddr, r.Addr)
|
copy(srcAddr, r.Addr)
|
||||||
var dstAddr net.IP
|
var dstAddr net.IP
|
||||||
switch r.AddrLen {
|
switch r.AddrLen {
|
||||||
case net.IPv4len:
|
case net.IPv4len:
|
||||||
dstAddr = addrMap(r.Addr, nftCidrV4)
|
dstAddr = addrMapGet(r.Addr, nftCidrV4, r.Ttl)
|
||||||
case net.IPv6len:
|
case net.IPv6len:
|
||||||
dstAddr = addrMap(r.Addr, nftCidrV6)
|
dstAddr = addrMapGet(r.Addr, nftCidrV6, r.Ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: clip ttl
|
|
||||||
r.Ttl = dnsClipTtl(r.Ttl)
|
|
||||||
// HACK: replace addr
|
// HACK: replace addr
|
||||||
copy(r.Addr, dstAddr)
|
copy(r.Addr, dstAddr)
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/sbin/nft -f
|
#!/usr/sbin/nft -f
|
||||||
|
|
||||||
define n_tele4 = 251.0.0.0/8
|
define n_tele4 = 198.18.0.0/15
|
||||||
define n_tele6 = 2001:db8:11::/48
|
define n_tele6 = 2001:db8:11::/80
|
||||||
|
|
||||||
table inet uni {
|
table inet uni {
|
||||||
|
|
||||||
|
12
go.mod
12
go.mod
@ -40,13 +40,13 @@ require (
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.23.0 // indirect
|
golang.org/x/crypto v0.24.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.18.0 // indirect
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.26.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.21.0 // indirect
|
||||||
golang.org/x/text v0.15.0 // indirect
|
golang.org/x/text v0.16.0 // indirect
|
||||||
golang.org/x/tools v0.21.0 // indirect
|
golang.org/x/tools v0.22.0 // indirect
|
||||||
google.golang.org/protobuf v1.34.1 // indirect
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
24
go.sum
24
go.sum
@ -97,22 +97,22 @@ github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmF
|
|||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
|
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
Loading…
Reference in New Issue
Block a user