diff --git a/src/cli/cli.go b/src/cli/cli.go index e1bc442..c8190f3 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -79,6 +79,7 @@ func Run() (err error) { cli.BoolFlag{Name: "stdout", Usage: "redirect file to stdout"}, cli.BoolFlag{Name: "ask", Usage: "make sure sender and recipient are prompted"}, cli.StringFlag{Name: "relay", Value: models.DEFAULT_RELAY, Usage: "address of the relay"}, + cli.StringFlag{Name: "relay6", Value: models.DEFAULT_RELAY6, Usage: "ipv6 address of the relay"}, cli.StringFlag{Name: "out", Value: ".", Usage: "specify an output folder to receive the file"}, cli.StringFlag{Name: "pass", Value: "pass123", Usage: "password for the relay"}, } @@ -143,6 +144,7 @@ func send(c *cli.Context) (err error) { Debug: c.GlobalBool("debug"), NoPrompt: c.GlobalBool("yes"), RelayAddress: c.GlobalString("relay"), + RelayAddress6: c.GlobalString("relay6"), Stdout: c.GlobalBool("stdout"), DisableLocal: c.Bool("no-local"), RelayPorts: strings.Split(c.String("ports"), ","), @@ -150,6 +152,11 @@ func send(c *cli.Context) (err error) { NoMultiplexing: c.Bool("no-multi"), RelayPassword: c.GlobalString("pass"), } + if crocOptions.RelayAddress != models.DEFAULT_RELAY { + crocOptions.RelayAddress6 = "" + } else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 { + crocOptions.RelayAddress = "" + } b, errOpen := ioutil.ReadFile(getConfigFile()) if errOpen == nil && !c.GlobalBool("remember") { var rememberedOptions croc.Options @@ -300,10 +307,16 @@ func receive(c *cli.Context) (err error) { Debug: c.GlobalBool("debug"), NoPrompt: c.GlobalBool("yes"), RelayAddress: c.GlobalString("relay"), + RelayAddress6: c.GlobalString("relay6"), Stdout: c.GlobalBool("stdout"), Ask: c.GlobalBool("ask"), RelayPassword: c.GlobalString("pass"), } + if crocOptions.RelayAddress != models.DEFAULT_RELAY { + crocOptions.RelayAddress6 = "" + } else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 { + crocOptions.RelayAddress = "" + } switch len(c.Args()) { case 1: diff --git a/src/croc/croc.go b/src/croc/croc.go index a652ac6..45a6a13 100644 --- a/src/croc/croc.go +++ b/src/croc/croc.go @@ -53,6 +53,7 @@ type Options struct { SharedSecret string Debug bool RelayAddress string + RelayAddress6 string RelayPorts []string RelayPassword string Stdout bool @@ -342,20 +343,32 @@ func (c *Client) Send(options TransferOptions) (err error) { } go func() { - host, port, err := net.SplitHostPort(c.Options.RelayAddress) - if err != nil { - log.Errorf("bad relay address %s", c.Options.RelayAddress) - return + var ipaddr, banner string + var conn *comm.Comm + durations := []time.Duration{100 * time.Millisecond, 5 * time.Second} + for i, address := range []string{c.Options.RelayAddress6, c.Options.RelayAddress} { + if address == "" { + continue + } + host, port, err := net.SplitHostPort(address) + if err != nil { + log.Errorf("bad relay address %s", address) + continue + } + // Default port to :9009 + if port == "" { + port = "9009" + } + log.Debugf("got host '%v' and port '%v'", host, port) + address = net.JoinHostPort(host, port) + log.Debugf("trying connection to %s", address) + conn, banner, ipaddr, err = tcp.ConnectToTCPServer(address, c.Options.RelayPassword, c.Options.SharedSecret[:3], durations[i]) + if err == nil { + c.Options.RelayAddress = address + break + } + log.Debugf("could not establish '%s'", address) } - // Default port to :9009 - if port == "" { - port = "9009" - } - log.Debugf("got host '%v' and port '%v'", host, port) - c.Options.RelayAddress = net.JoinHostPort(host, port) - log.Debugf("establishing connection to %s", c.Options.RelayAddress) - var banner string - conn, banner, ipaddr, err := tcp.ConnectToTCPServer(c.Options.RelayAddress, c.Options.RelayPassword, c.Options.SharedSecret[:3], 5*time.Second) if err != nil { err = fmt.Errorf("could not connect to %s: %w", c.Options.RelayAddress, err) log.Debug(err) @@ -486,26 +499,41 @@ func (c *Client) Receive() (err error) { } c.Options.RelayAddress = net.JoinHostPort(discoveries[0].Address, portToUse) c.ExternalIPConnected = c.Options.RelayAddress + c.Options.RelayAddress6 = "" usingLocal = true + break } } log.Debugf("discoveries: %+v", discoveries) log.Debug("establishing connection") } - host, port, err := net.SplitHostPort(c.Options.RelayAddress) - if err != nil { - log.Errorf("bad relay address %s", c.Options.RelayAddress) - return - } - // Default port to :9009 - if port == "" { - port = "9009" - } - c.Options.RelayAddress = net.JoinHostPort(host, port) - log.Debugf("establishing receiver connection to %s", c.Options.RelayAddress) var banner string - c.conn[0], banner, c.ExternalIP, err = tcp.ConnectToTCPServer(c.Options.RelayAddress, c.Options.RelayPassword, c.Options.SharedSecret[:3]) + durations := []time.Duration{100 * time.Millisecond, 5 * time.Second} + for i, address := range []string{c.Options.RelayAddress6, c.Options.RelayAddress} { + if address == "" { + continue + } + host, port, err := net.SplitHostPort(address) + if err != nil { + log.Errorf("bad relay address %s", address) + continue + } + // Default port to :9009 + if port == "" { + port = "9009" + } + log.Debugf("got host '%v' and port '%v'", host, port) + address = net.JoinHostPort(host, port) + log.Debugf("trying connection to %s", address) + c.conn[0], banner, c.ExternalIP, err = tcp.ConnectToTCPServer(address, c.Options.RelayPassword, c.Options.SharedSecret[:3], durations[i]) + if err == nil { + c.Options.RelayAddress = address + break + } + log.Debugf("could not establish '%s'", address) + } + log.Debugf("banner: %s", banner) if err != nil { err = fmt.Errorf("could not connect to %s: %w", c.Options.RelayAddress, err)