go-socks5 icon indicating copy to clipboard operation
go-socks5 copied to clipboard

Issues with custom dialer

Open kotori2 opened this issue 1 year ago • 2 comments

I want to customize the dialer so that it can dial outgoing connection using IPv6 address. However, this library will prefer DNS resolution by default. In a dual-stack environment and the client use socks5h (which means the hostname will not be resolved by the client), the resolved IP address might be IPv4, thus making the dialing failed.

Although I found a workaround that can pretend the name resolution success with empty result:

func (d YourResolver) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
	return ctx, []byte{}, nil
}

And it can trick the address formatter to use the FQDN instead: https://github.com/things-go/go-socks5/blob/6191a3489f54e890dbaeafc168c470c9fb2135e4/statute/addr.go#L19-L26

It depends on the fallback of the error case, so it's not ideal to implement like this. Considering we need to have backwards compatibility, we also can't change the resolve logic here:

https://github.com/things-go/go-socks5/blob/6191a3489f54e890dbaeafc168c470c9fb2135e4/handle.go#L50-L65

So I'm creating an issue looking for ideas to solve this issue.

kotori2 avatar Jan 06 '24 03:01 kotori2

Maybe your question is to force your custom resolver to return an ipv6 address?

You can try net.ResolveIPAddr("ip6", name) or other go resolver, maybe like following:

func (d DNSResolver) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
	addr, err := net.ResolveIPAddr("ip6", name)
	if err != nil {
		addr, err = net.ResolveIPAddr("ip4", name)
		if err != nil {
			return ctx, nil, err
		}
		return ctx, addr.IP, nil
	}
	return ctx, addr.IP, nil
}

cxz66666 avatar Feb 25 '24 16:02 cxz66666

Maybe your question is to force your custom resolver to return an ipv6 address?

You can try net.ResolveIPAddr("ip6", name) or other go resolver, maybe like following:

func (d DNSResolver) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
	addr, err := net.ResolveIPAddr("ip6", name)
	if err != nil {
		addr, err = net.ResolveIPAddr("ip4", name)
		if err != nil {
			return ctx, nil, err
		}
		return ctx, addr.IP, nil
	}
	return ctx, addr.IP, nil
}

So what I'm trying to do is that, I want to use user a for IPv4 outbound and b for IPv6 outbound. Although I can use ctx for storing user information, it will be way easier if we have the option to skip the domain resolution.

kotori2 avatar Feb 25 '24 20:02 kotori2