fix foreign dns blocking

This commit is contained in:
Vladimir Avtsenov 2024-10-22 23:23:07 +03:00
parent e2ecc511e7
commit 912f56246a
3 changed files with 39 additions and 8 deletions

View File

@ -15,6 +15,7 @@ import (
"github.com/rs/zerolog/log"
"github.com/vishvananda/netlink"
"github.com/vishvananda/netlink/nl"
)
var (
@ -26,6 +27,7 @@ type Config struct {
MinimalTTL time.Duration
ChainPrefix string
IpSetPrefix string
LinkName string
TargetDNSServerAddress string
ListenPort uint16
UseSoftwareRouting bool
@ -40,6 +42,8 @@ type App struct {
Records *Records
Groups map[int]*Group
Link netlink.Link
isRunning bool
dnsOverrider4 *netfilterHelper.PortRemap
dnsOverrider6 *netfilterHelper.PortRemap
@ -92,7 +96,12 @@ func (a *App) listen(ctx context.Context) (err error) {
}
}()
a.dnsOverrider4 = a.NetfilterHelper4.PortRemap(fmt.Sprintf("%sDNSOR", a.Config.ChainPrefix), 53, a.Config.ListenPort)
addrList, err := netlink.AddrList(a.Link, nl.FAMILY_ALL)
if err != nil {
return fmt.Errorf("failed to addrList address: %w", err)
}
a.dnsOverrider4 = a.NetfilterHelper4.PortRemap(fmt.Sprintf("%sDNSOR", a.Config.ChainPrefix), 53, a.Config.ListenPort, addrList)
err = a.dnsOverrider4.Enable()
if err != nil {
return fmt.Errorf("failed to override DNS (IPv4): %v", err)
@ -102,7 +111,7 @@ func (a *App) listen(ctx context.Context) (err error) {
_ = a.dnsOverrider4.Disable()
}()
a.dnsOverrider6 = a.NetfilterHelper6.PortRemap(fmt.Sprintf("%sDNSOR", a.Config.ChainPrefix), 53, a.Config.ListenPort)
a.dnsOverrider6 = a.NetfilterHelper6.PortRemap(fmt.Sprintf("%sDNSOR", a.Config.ChainPrefix), 53, a.Config.ListenPort, addrList)
err = a.dnsOverrider6.Enable()
if err != nil {
return fmt.Errorf("failed to override DNS (IPv6): %v", err)
@ -474,6 +483,12 @@ func New(config Config) (*App, error) {
app.Config = config
link, err := netlink.LinkByName(app.Config.LinkName)
if err != nil {
return nil, fmt.Errorf("failed to find link %s: %w", app.Config.LinkName, err)
}
app.Link = link
app.DNSProxy = dnsProxy.New(app.Config.ListenPort, app.Config.TargetDNSServerAddress)
app.DNSProxy.MsgHandler = app.handleMessage

View File

@ -18,6 +18,7 @@ func main() {
MinimalTTL: time.Hour,
ChainPrefix: "KVAS2_",
IpSetPrefix: "kvas2_",
LinkName: "br0",
TargetDNSServerAddress: "127.0.0.1:53",
ListenPort: 7548,
})

View File

@ -2,13 +2,17 @@ package netfilterHelper
import (
"fmt"
"github.com/coreos/go-iptables/iptables"
"net"
"strconv"
"github.com/coreos/go-iptables/iptables"
"github.com/vishvananda/netlink"
)
type PortRemap struct {
IPTables *iptables.IPTables
ChainName string
Addresses []netlink.Addr
From uint16
To uint16
@ -22,10 +26,20 @@ func (r *PortRemap) PutIPTable(table string) error {
return fmt.Errorf("failed to clear chain: %w", err)
}
// TODO: Add `-d <IP>`
err = r.IPTables.AppendUnique("nat", r.ChainName, "-p", "udp", "--dport", strconv.Itoa(int(r.From)), "-j", "DNAT", "--to-destination", fmt.Sprintf(":%d", r.To))
if err != nil {
return fmt.Errorf("failed to create rule: %w", err)
for _, addr := range r.Addresses {
var addrIP net.IP
iptablesProtocol := r.IPTables.Proto()
if (iptablesProtocol == iptables.ProtocolIPv4 && len(addr.IP) == net.IPv4len) || (iptablesProtocol == iptables.ProtocolIPv6 && len(addr.IP) == net.IPv6len) {
addrIP = addr.IP
}
if addrIP == nil {
continue
}
err = r.IPTables.AppendUnique("nat", r.ChainName, "-p", "udp", "-d", addrIP.String(), "--dport", strconv.Itoa(int(r.From)), "-j", "DNAT", "--to-destination", fmt.Sprintf(":%d", r.To))
if err != nil {
return fmt.Errorf("failed to create rule: %w", err)
}
}
err = r.IPTables.InsertUnique("nat", "PREROUTING", 1, "-j", r.ChainName)
@ -78,10 +92,11 @@ func (r *PortRemap) Enable() error {
return nil
}
func (nh *NetfilterHelper) PortRemap(name string, from, to uint16) *PortRemap {
func (nh *NetfilterHelper) PortRemap(name string, from, to uint16, addr []netlink.Addr) *PortRemap {
return &PortRemap{
IPTables: nh.IPTables,
ChainName: name,
Addresses: addr,
From: from,
To: to,
}