Skip to content

v1.12.14.25: CRITICAL FIX - HTTP Masquerade for TLS-less Mode

Choose a tag to compare

@ZhiShengYuan ZhiShengYuan released this 04 Feb 07:17
· 3453 commits to master since this release

Release Notes - v1.12.14.25

Release Date: 2026-02-04

Critical Bug Fix

This release fixes a critical bug in v1.12.14.24 where HTTP masquerade responses were not being sent properly.

Issue Fixed

Problem: TLS-less mode and HTTP/1.1 connections resulted in "Empty reply from server" errors.

Symptoms:

  • curl showing curl: (52) Empty reply from server
  • HTTP masquerade handler logs showing connection but no response sent
  • TLS-less mode (nginx upstream) not working

Root Causes:

  1. Headers were set AFTER calling WriteHeader() (incorrect order)
  2. Missing response body for redirect responses
  3. Missing Content-Length header for HTTP/1.1
  4. singleConnListener implementation caused premature connection closure

Changes

Fixed HTTP Response Order

  • String masquerade: Now sets headers BEFORE calling WriteHeader()
  • Redirect masquerade: Properly constructs response with all required fields

Added Required Headers and Body

// Now includes:
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Content-Length", strconv.Itoa(len(body)))
w.Write([]byte(body))  // Response body added

Replaced singleConnListener with oneShotListener

  • New implementation properly handles single-connection HTTP serving
  • Uses channel-based synchronization to prevent premature closure
  • Allows http.Server to complete response before cleanup

Testing

All redirect modes now work correctly:

Test 1: Root Path

$ curl -i http://127.0.0.1:8080/
HTTP/1.1 302 Found
Content-Length: 42
Content-Type: text/html; charset=utf-8
Location: https://example.com/

Test 2: Path with Query (append_request_uri: true)

$ curl -i http://127.0.0.1:8080/blog/article?id=123
HTTP/1.1 302 Found
Content-Length: 61
Content-Type: text/html; charset=utf-8
Location: https://example.com/blog/article?id=123

Test 3: Complex Paths

$ curl -i http://127.0.0.1:8080/docs/guide/installation
HTTP/1.1 302 Found
Content-Length: 65
Content-Type: text/html; charset=utf-8
Location: https://example.com/docs/guide/installation

Affected Configurations

This fix enables the following use cases that were broken in v1.12.14.24:

  1. TLS-less Mode (nginx upstream TLS termination)
  2. Redirect Masquerade (all status codes: 301, 302, 307, 308)
  3. HTTP/1.1 Connections (previously hanging)

Upgrade Recommendation

CRITICAL: Users of v1.12.14.24 should upgrade immediately. The redirect masquerade feature was non-functional in v1.12.14.24.

Files Changed

  • protocol/anytls/inbound.go:
    • Fixed string masquerade header order
    • Added response body to redirect masquerade
    • Added Content-Length and Content-Type headers
    • Replaced singleConnListener with oneShotListener
    • Added strconv import for Content-Length conversion

Backward Compatibility

✅ Fully backward compatible with v1.12.14.24 configurations.

  • All previous features remain unchanged
  • Bug fixes only, no breaking changes

Known Issues

None

Migration from v1.12.14.24

No configuration changes required. Simply replace the binary and restart.

Verification

To verify the fix works:

# Start sing-box with redirect masquerade
sing-box run -c config.json

# Test redirect (should get 302 response with body)
curl -i http://your-server:port/

# Expected output:
# HTTP/1.1 302 Found
# Content-Length: 42
# Content-Type: text/html; charset=utf-8
# Location: https://example.com/
#
# <a href="https://example.com/">Moved</a>.

Contributors

Bug fix by Claude Code (AI Assistant)

Related

  • Original feature: v1.12.14.24 - AnyTLS Redirect Masquerade
  • Documentation: docs/configuration/inbound/anytls.md
  • Examples: examples/anytls/