Skip to content

Commit a97e516

Browse files
lazkajbkempf
authored andcommitted
rsync: support rsync-ssl connections too
rsync provides a rsync-ssl script which tries to communicate over tls, on port 874 instead of 873, if it finds openssl/gnutls/stunnel. In theory we could add a separate cli option for this since there is no official URL scheme for rsync+tls, but to keep things simple for everyone just allow rsyncs:// in rsync URLs. In case a URL is starting with rsyncs:// we will use rsync-ssl instead of rsync, and rewrite the url back to rsync://. For testing, here are two public servers that support TLS: * rsync-ssl rsync://mirrors.dotsrc.org * rsync-ssl rsync://repo.msys2.org Using "--contimeout" with rsync-ssl leads to: "The --contimeout option may only be used when connecting to an rsync daemon." From my testing "--timeout" aborts though if openssl takes too long to connect, suggesting that it covers both connection and i/o in this scenario. Bump the --timeout to 60 so the upper bound is the same as without openssl.
1 parent b97052a commit a97e516

1 file changed

Lines changed: 25 additions & 6 deletions

File tree

scan/rsync.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,21 @@ type RsyncScanner struct {
3232
// Scan starts an rsync scan of the given mirror
3333
func (r *RsyncScanner) Scan(rsyncURL, identifier string, conn redis.Conn, stop <-chan struct{}) (core.Precision, error) {
3434
var env []string
35-
36-
if !strings.HasPrefix(rsyncURL, "rsync://") {
37-
return 0, fmt.Errorf("%s does not start with rsync://", rsyncURL)
35+
var cmdName string
36+
var actualURL string
37+
38+
// We allow a custom rsyncs:// scheme which uses rsync-ssl instead
39+
if strings.HasPrefix(rsyncURL, "rsync://") {
40+
cmdName = "rsync"
41+
actualURL = rsyncURL
42+
} else if strings.HasPrefix(rsyncURL, "rsyncs://") {
43+
cmdName = "rsync-ssl"
44+
actualURL = "rsync://" + strings.TrimPrefix(rsyncURL, "rsyncs://")
45+
} else {
46+
return 0, fmt.Errorf("%s does not start with rsync:// or rsyncs://", rsyncURL)
3847
}
3948

40-
u, err := url.Parse(rsyncURL)
49+
u, err := url.Parse(actualURL)
4150
if err != nil {
4251
return 0, err
4352
}
@@ -58,7 +67,17 @@ func (r *RsyncScanner) Scan(rsyncURL, identifier string, conn redis.Conn, stop <
5867
// Don't use the local timezone, use UTC
5968
env = append(env, "TZ=UTC")
6069

61-
cmd := exec.Command("rsync", "-r", "--no-motd", "--timeout=30", "--contimeout=30", "--exclude=.~tmp~/", u.String())
70+
args := []string{"-r", "--no-motd", "--exclude=.~tmp~/"}
71+
// rsync-ssl does not support --contimeout, but from what I see --timeout covers both and
72+
// triggers if openssl takes too long to connect. So use a longer combined timeout there.
73+
if cmdName == "rsync-ssl" {
74+
args = append(args, "--timeout=60")
75+
} else {
76+
args = append(args, "--timeout=30", "--contimeout=30")
77+
}
78+
args = append(args, u.String())
79+
80+
cmd := exec.Command(cmdName, args...)
6281

6382
// Setup the environnement
6483
cmd.Env = env
@@ -86,7 +105,7 @@ func (r *RsyncScanner) Scan(rsyncURL, identifier string, conn redis.Conn, stop <
86105
return 0, err
87106
}
88107

89-
log.Infof("[%s] Requesting file list via rsync...", identifier)
108+
log.Infof("[%s] Requesting file list via %s...", identifier, cmdName)
90109

91110
scanfinished := make(chan bool)
92111
go func() {

0 commit comments

Comments
 (0)