@@ -225,69 +225,47 @@ func (c *DNSRedirectComponent) createChainAndRules(ipt *iptables.IPTables, addre
225225 }
226226 }
227227
228- // Determine IP version
229- isIPv6Table := ipt .Proto () == iptables .ProtocolIPv6
230-
231- // Add rules for each local address
232- for _ , addr := range addresses {
233- // Skip addresses that don't match this IP version
234- isIPv4 := addr .IP .To4 () != nil
228+ // Get list of interfaces instead of addresses
229+ links , err := netlink .LinkList ()
230+ if err != nil {
231+ return fmt .Errorf ("failed to list links: %w" , err )
232+ }
235233
236- if isIPv4 && isIPv6Table {
237- continue
238- }
239- if ! isIPv4 && ! isIPv6Table {
234+ // Create a set of unique interface names to avoid duplicates
235+ interfaceSet := make (map [string ]bool )
236+ for _ , link := range links {
237+ ifName := link .Attrs ().Name
238+ // Skip loopback interface
239+ if ifName == "lo" {
240240 continue
241241 }
242+ interfaceSet [ifName ] = true
243+ }
242244
243- // For IPv4: use REDIRECT (preserves original destination IP)
244- // For IPv6: use DNAT with port-only destination
245- if ! isIPv6Table {
246- // IPv4: REDIRECT --to-port
247- udpRule := []string {
248- "-p" , "udp" ,
249- "-d" , addr .IP .String (),
250- "--dport" , strconv .Itoa (dnsSourcePort ),
251- "-j" , "REDIRECT" ,
252- "--to-port" , strconv .Itoa (int (c .targetPort )),
253- }
254- if err := ipt .AppendUnique ("nat" , dnsRedirectChainName , udpRule ... ); err != nil {
255- return fmt .Errorf ("failed to add UDP rule: %w" , err )
256- }
257-
258- tcpRule := []string {
259- "-p" , "tcp" ,
260- "-d" , addr .IP .String (),
261- "--dport" , strconv .Itoa (dnsSourcePort ),
262- "-j" , "REDIRECT" ,
263- "--to-port" , strconv .Itoa (int (c .targetPort )),
264- }
265- if err := ipt .AppendUnique ("nat" , dnsRedirectChainName , tcpRule ... ); err != nil {
266- return fmt .Errorf ("failed to add TCP rule: %w" , err )
267- }
268- } else {
269- // IPv6: DNAT --to-destination :<port>
270- udpRule := []string {
271- "-p" , "udp" ,
272- "-d" , addr .IP .String (),
273- "--dport" , strconv .Itoa (dnsSourcePort ),
274- "-j" , "DNAT" ,
275- "--to-destination" , fmt .Sprintf (":%d" , c .targetPort ),
276- }
277- if err := ipt .AppendUnique ("nat" , dnsRedirectChainName , udpRule ... ); err != nil {
278- return fmt .Errorf ("failed to add UDP rule: %w" , err )
279- }
245+ // Add rules for each interface
246+ // Match on incoming interface + destination port 53, redirect to target port
247+ // This works for all IP addresses (IPv4, global IPv6, link-local IPv6)
248+ for ifName := range interfaceSet {
249+ udpRule := []string {
250+ "-i" , ifName ,
251+ "-p" , "udp" ,
252+ "--dport" , strconv .Itoa (dnsSourcePort ),
253+ "-j" , "REDIRECT" ,
254+ "--to-ports" , strconv .Itoa (int (c .targetPort )),
255+ }
256+ if err := ipt .AppendUnique ("nat" , dnsRedirectChainName , udpRule ... ); err != nil {
257+ return fmt .Errorf ("failed to add UDP rule for %s: %w" , ifName , err )
258+ }
280259
281- tcpRule := []string {
282- "-p" , "tcp" ,
283- "-d" , addr .IP .String (),
284- "--dport" , strconv .Itoa (dnsSourcePort ),
285- "-j" , "DNAT" ,
286- "--to-destination" , fmt .Sprintf (":%d" , c .targetPort ),
287- }
288- if err := ipt .AppendUnique ("nat" , dnsRedirectChainName , tcpRule ... ); err != nil {
289- return fmt .Errorf ("failed to add TCP rule: %w" , err )
290- }
260+ tcpRule := []string {
261+ "-i" , ifName ,
262+ "-p" , "tcp" ,
263+ "--dport" , strconv .Itoa (dnsSourcePort ),
264+ "-j" , "REDIRECT" ,
265+ "--to-ports" , strconv .Itoa (int (c .targetPort )),
266+ }
267+ if err := ipt .AppendUnique ("nat" , dnsRedirectChainName , tcpRule ... ); err != nil {
268+ return fmt .Errorf ("failed to add TCP rule for %s: %w" , ifName , err )
291269 }
292270 }
293271
0 commit comments