fix: add ipv6 support

This commit is contained in:
SunBK201 2025-12-09 21:03:12 +08:00
parent dfe1999616
commit b939858257
3 changed files with 83 additions and 11 deletions

View File

@ -155,6 +155,16 @@ func (f *Firewall) AddTproxyRoute(fwmark, routeTable string) error {
return fmt.Errorf("cmd.Run: %w", err)
}
cmd = exec.Command("ip", "-6", "rule", "add", "fwmark", fwmark, "table", routeTable)
if err := cmd.Run(); err != nil {
slog.Warn("ip -6 rule add", slog.String("error", err.Error()))
}
cmd = exec.Command("ip", "-6", "route", "add", "local", "::/0", "dev", "lo", "table", routeTable)
if err := cmd.Run(); err != nil {
slog.Warn("ip -6 route add", slog.String("error", err.Error()))
}
return nil
}
@ -165,6 +175,12 @@ func (f *Firewall) DeleteTproxyRoute(fwmark, routeTable string) error {
cmd = exec.Command("ip", "route", "flush", "table", routeTable)
_ = cmd.Run()
cmd = exec.Command("ip", "-6", "rule", "del", "fwmark", fwmark, "table", routeTable)
_ = cmd.Run()
cmd = exec.Command("ip", "-6", "route", "flush", "table", routeTable)
_ = cmd.Run()
return nil
}

View File

@ -3,10 +3,13 @@
package base
import (
"encoding/binary"
"errors"
"fmt"
"log/slog"
"net"
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
@ -37,18 +40,43 @@ func GetOriginalDstAddr(conn net.Conn) (addr string, err error) {
return "", errors.New("GetConnFD connection is not *net.TCPConn")
}
file, err := tcpConn.File()
rawConn, err := tcpConn.SyscallConn()
if err != nil {
return "", fmt.Errorf("tcpConn.File: %v", err)
}
defer file.Close()
raw, err := unix.GetsockoptIPv6Mreq(int(file.Fd()), unix.SOL_IP, unix.SO_ORIGINAL_DST)
if err != nil {
return "", fmt.Errorf("unix.GetsockoptIPv6Mreq: %v", err)
return "", fmt.Errorf("SyscallConn: %v", err)
}
ip := net.IPv4(raw.Multiaddr[4], raw.Multiaddr[5], raw.Multiaddr[6], raw.Multiaddr[7])
port := uint16(raw.Multiaddr[2])<<8 + uint16(raw.Multiaddr[3])
return fmt.Sprintf("%s:%d", ip.String(), port), nil
var originalAddr string
err = rawConn.Control(func(fd uintptr) {
level := syscall.IPPROTO_IP
if conn.RemoteAddr().String()[0] == '[' {
level = syscall.IPPROTO_IPV6
}
addr, err := syscall.GetsockoptIPv6MTUInfo(int(fd), level, unix.SO_ORIGINAL_DST)
if err != nil {
slog.Warn("unix.GetsockoptIPv6MTUInfo", "error", err)
return
}
var ip net.IP
if level == syscall.IPPROTO_IPV6 {
ip = net.IP(addr.Addr.Addr[:])
} else {
ipBytes := (*[4]byte)(unsafe.Pointer(&addr.Addr.Flowinfo))[:4]
ip = net.IPv4(ipBytes[0], ipBytes[1], ipBytes[2], ipBytes[3])
}
port := binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&addr.Addr.Port))[:2])
if level == syscall.IPPROTO_IPV6 {
originalAddr = fmt.Sprintf("[%s]:%d", ip.String(), port)
} else {
originalAddr = fmt.Sprintf("%s:%d", ip.String(), port)
}
})
if err != nil {
return "", fmt.Errorf("rawConn.Control: %v", err)
}
return originalAddr, nil
}

View File

@ -96,6 +96,16 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table)
"counter accept",
),
})
tx.Add(&knftables.Rule{
Chain: sidecar.Name,
Rule: knftables.Concat(
"meta l4proto tcp",
"mark", s.tproxyFwMark,
"mark set 7894",
fmt.Sprintf("tproxy ip6 to [::1]:%d", s.Cfg.Port),
"counter accept",
),
})
}
prerouting := &knftables.Chain{
@ -175,6 +185,15 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table)
"counter accept",
),
})
tx.Add(&knftables.Rule{
Chain: prerouting.Name,
Rule: knftables.Concat(
"meta l4proto tcp",
"mark", s.tproxyFwMark,
fmt.Sprintf("tproxy ip6 to [::1]:%d", s.Cfg.Port),
"counter accept",
),
})
// default less hit. sc.
tx.Add(&knftables.Rule{
@ -186,6 +205,15 @@ func (s *Server) NftSetTproxy(tx *knftables.Transaction, table *knftables.Table)
"counter accept",
),
})
tx.Add(&knftables.Rule{
Chain: prerouting.Name,
Rule: knftables.Concat(
"meta l4proto tcp",
"mark set", s.tproxyFwMark,
fmt.Sprintf("tproxy ip6 to [::1]:%d", s.Cfg.Port),
"counter accept",
),
})
output := &knftables.Chain{
Name: "OUTPUT",