大多数服务器的行为会导致错误。

目前没有一个代理协议规定了向服务器发送具有域名的 UDP 包后,服务器应如何处理响应中的地址。实际上,大多数代理程序服务器,如 Shadowsocks 官方实现 和 V2Ray,在响应中只返回 IP 地址。

当代理程序向服务器发送域名时,它并不知道该域名对应的 IP 地址。当服务器在响应中发送 IP 地址时,该地址可能与客户端发起连接的目标地址不匹配。如果客户端验证该地址,该连接将失败。

因此,像 Clash 和 Xray 这样支持 fake-ip 的透明代理客户端会强制在发起 UDP 代理连接之前将域名解析为 IP 地址。因此,实际上你几乎不能这样做。

在 Clash 中:

func handleUDPConn(packet *inbound.PacketAdapter) {
	...

	// local resolve UDP dns
	if !metadata.Resolved() {
		ips, err := resolver.LookupIP(context.Background(), metadata.Host)
		if err != nil || len(ips) == 0 {
			packet.Drop()
			return
		}
		metadata.DstIP = ips[0]
	}
	
	...
}

在 Xray 中:

func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sniffing session.SniffingRequest) (*transport.Link, *transport.Link) {
	...

	if addr.Family().IsIP() {
		...
	} else {
		if ip2domain == nil {
			ip2domain = new(sync.Map)
			newError("[fakedns client] create a new map").WriteToLog(session.ExportIDToError(ctx))
		}
		domain := addr.Domain()
		ips, err := d.dns.LookupIP(domain, dns.IPOption{true, true, false})
		if err == nil {
			for _, ip := range ips {
				ip2domain.Store(ip.String(), domain)
			}
			newError("[fakedns client] candidate ip: "+fmt.Sprintf("%v", ips), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
		} else {
			newError("[fakedns client] failed to look up IP for ", domain, " for xUDP buffer at ", i).Base(err).WriteToLog(session.ExportIDToError(ctx))
		}
	}

	...
}

如果您确实想尝试,则请确保您使用 sing-box :)