Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Add UDP SO_REUSEADDR Support to make mosdns compatible with UDP TPROXY #657

Open
wants to merge 1 commit into
base: v4
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions coremain/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ type ServerListenerConfig struct {
ProxyProtocol bool `yaml:"proxy_protocol"` // accepting the PROXYProtocol

IdleTimeout uint `yaml:"idle_timeout"` // (sec) used by tcp, dot, doh as connection idle timeout.

// Issue: https://github.com/IrineSistiana/mosdns/pull/657
// When a TPROXY is processing a UDP connection,
// for example: if the Dest Addr is 8.8.8.8:53,
// the TPROXY program must bind to 8.8.8.8:53 on TPROXY host os
// and send the UDP packet back to the Client to make sure the Src Addr and Port is 8.8.8.8:53 ,
// IF, when mosdns has bind :53 on this host os without SO_REUSEADDR,
// the behavior of the TPROXY program will fail with EADDRINUSE (Address already in use)
ReuseAddr bool `yaml:"reuse_addr"` // used by udp on unix alike systems.
}

type APIConfig struct {
Expand Down
10 changes: 9 additions & 1 deletion coremain/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package coremain

import (
"context"
"errors"
"fmt"
"github.com/IrineSistiana/mosdns/v4/pkg/server"
Expand All @@ -28,6 +29,7 @@ import (
"github.com/pires/go-proxyproto"
"go.uber.org/zap"
"net"
"syscall"
"time"
)

Expand Down Expand Up @@ -115,7 +117,13 @@ func (m *Mosdns) startServerListener(cfg *ServerListenerConfig, dnsHandler dns_h
var run func() error
switch cfg.Protocol {
case "", "udp":
conn, err := net.ListenPacket("udp", cfg.Addr)
// see also: https://github.com/IrineSistiana/mosdns/pull/657
var lc net.ListenConfig
lc.Control = func(network, address string, c syscall.RawConn) error {
return serverSocketOption(c, cfg, network, address)
}

conn, err := lc.ListenPacket(context.Background(), "udp", cfg.Addr)
if err != nil {
return err
}
Expand Down
15 changes: 15 additions & 0 deletions coremain/utilities_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build !(linux || darwin || freebsd || netbsd || openbsd)

package coremain

import (
"errors"
"syscall"
)

func serverSocketOption(c syscall.RawConn, cfg *ServerListenerConfig, network, address string) error {
if cfg.ReuseAddr {
return errors.New("reuseaddr not supported on this platform")
}
return nil
}
20 changes: 20 additions & 0 deletions coremain/utilities_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//go:build linux || darwin || freebsd || netbsd || openbsd

package coremain

import (
"syscall"
)

func serverSocketOption(c syscall.RawConn, cfg *ServerListenerConfig, network, address string) error {
var errSysCall error
errControl := c.Control(func(fd uintptr) {
if cfg.ReuseAddr {
errSysCall = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
}
})
if errSysCall != nil {
return errSysCall
}
return errControl
}