diff --git a/docs/content/docs.md b/docs/content/docs.md index c229bef19..a520424e0 100644 --- a/docs/content/docs.md +++ b/docs/content/docs.md @@ -641,6 +641,9 @@ IPv4 address (1.2.3.4), an IPv6 address (1234::789A) or host name. If the host name doesn't resolve or resolves to more than one IP address it will give an error. +You can use `--bind 0.0.0.0` to force rclone to use IPv4 addresses and +`--bind ::0` to force rclone to use IPv6 addresses. + ### --bwlimit=BANDWIDTH_SPEC ### This option controls the bandwidth limit. For example diff --git a/fs/fshttp/dialer.go b/fs/fshttp/dialer.go index adeece185..a41b478b8 100644 --- a/fs/fshttp/dialer.go +++ b/fs/fshttp/dialer.go @@ -52,6 +52,17 @@ var warnDSCPFail, warnDSCPWindows sync.Once // DialContext connects to the network address using the provided context. func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) { + // If local address is 0.0.0.0 or ::0 force IPv4 or IPv6 + // This works around https://github.com/golang/go/issues/48723 + // Which means 0.0.0.0 and ::0 both bind to both IPv4 and IPv6 + if ip, ok := d.Dialer.LocalAddr.(*net.TCPAddr); ok && ip.IP.IsUnspecified() && (network == "tcp" || network == "udp") { + if ip.IP.To4() != nil { + network += "4" // IPv4 address + } else { + network += "6" // IPv6 address + } + } + c, err := d.Dialer.DialContext(ctx, network, address) if err != nil { return c, err