[NETransparentProxyProvider] NEAppProxyUDPFlow.writeDatagrams sentByEndpoints ipv4 address will become "", ipv6 address can work.

Sorry, my English is not good.

I use NETransparentProxyProvider to implement a global proxy program, and the tcp and udp connections will be passed to the remote proxy server by the TransparentProxy system extension.

But now I have a problem, the package sent through NEAppProxyUDPFlow.writeDatagrams, when the address is ipv6, the normal program taken over by the proxy can correctly get the address of the udp package. But when the address is IPv4, the normal program taken over by the proxy can only get the source port number of the packet, and the obtained ip address will be blank.

TransparentProxy system extension NEAppProxyUDPFlow.writeDatagrams code to send packets:

// NWHostEndpoint *hostAddr = [NWHostEndpoint endpointWithHostname:@"::11:22:33:44" port:@"5566"];
             NWHostEndpoint *hostAddr = [NWHostEndpoint endpointWithHostname:@"1.2.3.4" port:@"5566"];

             NWEndpoint* addr = hostAddr;
           // _internalEndpoint NWOSAddressEndpoint * 0x151804ce0 0x0000000151804ce0
           os_log(OS_LOG_DEFAULT, "[DEBUG] appproxy-test-LocalUdpConn(%{public}@)-writeLoop uFlow writeDatagrams addr:%{public}@ ",uuid,addr.debugDescription);
             [uFlow writeDatagrams:@[udpPack.data] sentByEndpoints:@[addr] completionHandler:^(NSError *error) {
...
}

TransparentProxy system extension log:

[DEBUG] appproxy-test-LocalUdpConn(6B0C27A0-588E-4D2B-8544-AE927522DD25)-writeLoop uFlow writeDatagrams addr:1.2.3.4:5566

The log shows that the address should be 1.2.3.4:5566. But the ip address actually obtained by the local program taken over by the extension is empty, see below.

Local udp test program:



package main

import (
	"log"
	"net"
)

func main() {
	l, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.IPv4(0, 0, 0, 0),
		Port: 0,
		Zone: "",
	})
	if err != nil {
		panic(err)
	}
	defer l.Close()

	wData := []byte("0123456789")

	addr, err := net.ResolveUDPAddr("udp", "1.2.3.4:8088")
	if err != nil {
		panic(err)
	}

	for {
		log.Printf("Send a ping to %v...", addr)
		n, err := l.WriteTo(wData, addr)
		if err != nil {
			log.Printf("l.writeTo(%v), %v", addr, err)
			return
		}

		if n != len(wData) {
			log.Printf("%v!=%v", n, len(wData))
		}

		buf := make([]byte, 1024)

		log.Printf("Receive pong...")
		n, rAddr, err := l.ReadFromUDP(buf)
		if err != nil {
			log.Printf("%v", err)
			return
		}

		log.Printf("rAddr:%v", rAddr)
	}
}

Local test program log:

2023/08/14 19:34:34 Send a ping to 1.2.3.4:8088...
2023/08/14 19:34:34 Receive pong...
2023/08/14 19:34:34 rAddr:[::]:5566
2023/08/14 19:34:34 Send a ping to 1.2.3.4:8088...
2023/08/14 19:34:34 Receive pong...
2023/08/14 19:34:34 rAddr:[::]:5566
2023/08/14 19:34:34 Send a ping to 1.2.3.4:8088...
2023/08/14 19:34:34 Receive pong...
2023/08/14 19:34:34 rAddr:[::]:5566
2023/08/14 19:34:34 Send a ping to 1.2.3.4:8088...
2023/08/14 19:34:34 Receive pong...

After changing to IPv6 address, the ip address can be obtained normally.

System extensions:

             NWHostEndpoint *hostAddr = [NWHostEndpoint endpointWithHostname:@"::11:22:33:44" port:@"5566"];
// NWHostEndpoint *hostAddr = [NWHostEndpoint endpointWithHostname:@"1.2.3.4" port:@"5566"];

Local test program log:

2023/08/14 19:43:27 Send a ping to 1.2.3.4:8088...
2023/08/14 19:43:27 Receive pong...
2023/08/14 19:43:27 rAddr:[::11:22:33:44]:5566
2023/08/14 19:43:27 Send a ping to 1.2.3.4:8088...
2023/08/14 19:43:27 Receive pong...
2023/08/14 19:43:27 rAddr:[::11:22:33:44]:5566
2023/08/14 19:43:27 Send a ping to 1.2.3.4:8088...
2023/08/14 19:43:27 Receive pong...
2023/08/14 19:43:27 rAddr:[::11:22:33:44]:5566
2023/08/14 19:43:27 Send a ping to 1.2.3.4:8088...
2023/08/14 19:43:27 Receive pong...

It can be seen that when the address is an IPv6 address, the ip address can be obtained correctly.

Where should this be the problem? How should it be corrected?

Thank you so much.

OS version is: 13.4.1 (c) hardware : MacBook Air M1 xcode: Version 14.2 (14C18)

Okay, to rule out any such issues with your test program, have you tried this with Safari flows or even netcat generate flows to make sure that you know that traffic is being organically generated and sent to your proxy? The majority of Safari will be TCP based flows but there should also be UDP flows for sites that use QUIC etc..

[NETransparentProxyProvider] NEAppProxyUDPFlow.writeDatagrams sentByEndpoints ipv4 address will become "", ipv6 address can work.
 
 
Q