XTLS/Xray-core · error

failed to create unexpected ip matcher

Error message

failed to create unexpected ip matcher

What it means

After the header and length checks pass, readPaddingTurn drains the padding body in 16 KiB reads via io.ReadFull; this error wraps that read failing. It means the connection died or truncated mid-turn: EOF/ErrUnexpectedEOF (peer closed before sending all padding bytes), reset, deadline exceeded, or read-side cancellation.

Source

Thrown at app/dns/nameserver.go:125

		_, isLocalDNS := server.(*LocalNameServer)
		updateRules(isLocalDNS)

		// Establish expected IPs
		var expectedMatcher geodata.IPMatcher
		if len(ns.ExpectedIp) > 0 {
			expectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.ExpectedIp)
			if err != nil {
				return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
			}
		}

		// Establish unexpected IPs
		var unexpectedMatcher geodata.IPMatcher
		if len(ns.UnexpectedIp) > 0 {
			unexpectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.UnexpectedIp)
			if err != nil {
				return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
			}
		}

		if len(clientIP) > 0 {
			switch ns.Address.Address.GetAddress().(type) {
			case *net.IPOrDomain_Domain:
				errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
			case *net.IPOrDomain_Ip:
				errors.LogInfo(ctx, "DNS: client ", net.IP(ns.Address.Address.GetIp()), " uses clientIP ", clientIP.String())
			}
		}

		timeoutMs := 4000 * time.Millisecond
		if ns.TimeoutMs > 0 {
			timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond
		}

		checkSystem := ns.QueryStrategy == QueryStrategy_USE_SYS

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Raise the connection read deadline above the sender's maximum total padding delay (start delay + sum of chunk delays)
  2. Classify via errors.Is(err, io.ErrUnexpectedEOF) etc. and reconnect - partial turns cannot be resumed
  3. Reduce configured delay ranges if intermediaries time out the padded stream

Example fix

// before
conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
// after
conn.SetReadDeadline(time.Now().Add(30 * time.Second))
Defensive patterns

Strategy: retry

Try / catch

if err := readPaddingTurn(r, turn, prefix); err != nil {
    if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) || os.IsTimeout(errors.Unwrap(err)) {
        // truncated/dead turn: discard connection, reconnect with backoff
    }
}

Prevention

When it happens

Trigger: Peer aborts after sending only part of its padding record; read deadline shorter than the peer's injected padding delays; middlebox cutting long padded bursts; TLS layer failing underneath.

Common situations: Aggressive chunk delays on the sender exceeding the receiver's read timeout; mobile networks dropping mid-handshake; LBs with per-read idle limits; sender crashing between chunks.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/fd2213c398fb822f. Report an issue: GitHub.