shadow1ng/fscan · error
rsync_connect_failed
Error message
rsync_connect_failed
What it means
doRsyncAuth first opens a TCP connection and requests the module list via connectToRsync. If connectToRsync returns nil (connection or LIST-phase handshake failed), the auth attempt is aborted with rsync_connect_failed and ErrorTypeNetwork, indicating a network-level or protocol-level failure to talk to the rsync daemon.
Source
Thrown at plugins/services/rsync.go:113
}
}
// createAuthFunc 创建Rsync认证函数
func (p *RsyncPlugin) createAuthFunc(info *common.HostInfo, session *common.ScanSession) AuthFunc {
return func(ctx context.Context, cred Credential) *AuthResult {
return p.doRsyncAuth(ctx, info, cred, session)
}
}
// doRsyncAuth 执行Rsync认证
func (p *RsyncPlugin) doRsyncAuth(ctx context.Context, info *common.HostInfo, cred Credential, session *common.ScanSession) *AuthResult {
// 先获取可用模块列表
conn := p.connectToRsync(ctx, info, session)
if conn == nil {
return &AuthResult{
Success: false,
ErrorType: ErrorTypeNetwork,
Error: fmt.Errorf("%s", i18n.GetText("rsync_connect_failed")),
}
}
modules := p.getModules(conn, session.Config)
_ = conn.Close()
if len(modules) == 0 {
return &AuthResult{
Success: false,
ErrorType: ErrorTypeUnknown,
Error: fmt.Errorf("%s", i18n.GetText("rsync_modules_failed")),
}
}
// 提取第一个模块名
var firstModule string
for _, moduleLine := range modules {
if fields := strings.Fields(moduleLine); len(fields) > 0 {
firstModule = fields[0]View on GitHub (pinned to 95cc12e753)
Solutions
- Verify the rsync daemon is reachable: nc -vz <host> 873 or telnet and expect the @RSYNCD banner.
- Confirm the daemon port matches the scan target (port option in rsyncd.conf / non-default ports).
- Check rsyncd.conf 'hosts allow'/'hosts deny' so the scanner IP is permitted.
- Increase the connection timeout in the scan config for slow links.
Example fix
// before (wrong port) target := "10.0.0.5:22" // rsync_connect_failed // after target := "10.0.0.5:873" // @RSYNCD 31.0 banner received
Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", host+":873", 5*time.Second)
if err != nil { /* skip host: rsync not reachable */ }
else { conn.SetReadDeadline(time.Now().Add(3*time.Second)); buf := make([]byte, 64); n, _ := conn.Read(buf); if !strings.HasPrefix(string(buf[:n]), "@RSYNCD") { /* not rsync */ } conn.Close() } Try / catch
res, err := plugin.Scan(ctx, target)
if err != nil && strings.Contains(err.Error(), "rsync_connect_failed") {
// transient network? retry with backoff, else mark host unreachable
} Prevention
- Preflight the @RSYNCD banner before auth attempts.
- Keep connection timeouts generous (>=5s) for remote scans.
- Maintain a reachability check (TCP dial) upstream of the rsync module.
When it happens
Trigger: connectToRsync cannot dial info.Target() within the timeout, the TCP connection is refused/reset, or the initial rsync protocol handshake (@RSYNCD greeting) does not complete, so the function returns nil and the error is raised at rsync.go:113.
Common situations: rsync daemon not running or bound to a different port; firewall dropping 873; module list restricted by hosts allow/deny; daemon configured with 'list = no' or proxy in between; network timeouts in cloud environments.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- i18n.Tr("service_connection_failed", "%w")
- ms17010_connection_error: %w
- failed to connect host: %s
- network_rate_limited
- [dial err] %v
AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06).
Data as JSON: /api/errors/27f63c0d9703188d.
Report an issue: GitHub.