Skip to content

[bug] TLV Parsing Issue in proxy-protocol-js Causing MQTT Connection Failure with Certain Cloud Providers #12

@it16888

Description

@it16888

Issue Description
When using Aedes MQTT broker with proxy-protocol-js@4.0.6 dependency to handle MQTT connections, Cloud Provider A's MQTT service fails to connect properly, while Cloud Provider B's MQTT service works normally. Investigation revealed an issue in the TLV (Type-Length-Value) parsing section of proxy-protocol-js.

Environment Information
Aedes Version: 0.51.3
Dependency: proxy-protocol-js@4.0.6
Node.js Version: v22.14.0
Operating System: Debian 12
Protocol: PROXY Protocol v2
Steps to Reproduce
Set up Aedes MQTT broker with proxy-protocol-js@4.0.6 for PROXY Protocol v2 support
Connect to Cloud Provider A's MQTT service
Connection fails with TLV parsing exception
Expected Behavior
Should correctly parse TLV fields in the PROXY Protocol v2 header sent by Cloud Provider A's MQTT service and successfully establish the connection.

Actual Behavior
TLV parsing fails, preventing connection establishment. The same Aedes configuration works normally with Cloud Provider B's MQTT service.

Problem Analysis
Different cloud service providers may have subtle differences in their PROXY Protocol v2 TLV implementations:

TLV Field Order: Cloud Provider A and B may use different TLV field ordering
TLV Type Values: May use different custom TLV types
TLV Length Calculation: Length field parsing may have improper edge case handling
Optional TLV Fields: Cloud Provider A may include certain special TLV extension fields
Possible Root Cause
The current TLV parsing implementation may:

Have overly strict or insufficiently robust TLV field length validation
Not properly handle unknown TLV types
Have offset calculation errors when parsing multiple TLV fields
Have incomplete boundary checks for TLV data
Suggested Fix Directions
Enhance TLV parsing fault tolerance to skip unknown TLV types
Improve length field validation logic to ensure correct edge case handling
Add more detailed debug logging to help diagnose differences between cloud providers
Reference RFC specifications to ensure implementation complies with PROXY Protocol v2 standard
Additional Information
Cloud Provider B MQTT Connection: ✅ Works normally
Cloud Provider A MQTT Connection: ❌ TLV parsing failure
Impact Scope
This issue affects all Aedes MQTT broker deployments connecting to Cloud Provider A's MQTT service that rely on proxy-protocol-js for PROXY Protocol parsing.

Temporary Workaround
We have implemented a temporary patch to skip TLV field parsing. The patch modifies the V2ProxyProtocol.js file in proxy-protocol-js:

Original Code:

var addressFamily = new AddressFamily_1.AddressFamily(addressFamilyType);
var addressFamilyLength = addressFamily.getLength();
if (length < addressFamilyLength) {
throw new V2ProxyProtocolParseError("given specified length is shorter than address family's length");
}
return new V2ProxyProtocol(command, transportProtocol, addressFamily.getFactoryMethod()(input.slice(16)), input.slice(addressFamilyLength + 16));
Patched Code:

var addressFamily = new AddressFamily_1.AddressFamily(addressFamilyType);
var addressFamilyLength = addressFamily.getLength();
if (length < addressFamilyLength) {
throw new V2ProxyProtocolParseError("given specified length is shorter than address family's length");
}
// Skip TLV fields, only return actual application data
// length includes address + TLV, addressFamilyLength is only address length
var dataStartOffset = 16 + length; // 16 is fixed header length, length is total address + TLV length
return new V2ProxyProtocol(command, transportProtocol, addressFamily.getFactoryMethod()(input.slice(16)), input.slice(dataStartOffset));
Key Change: Instead of using input.slice(addressFamilyLength + 16) which attempts to parse TLV fields, we use input.slice(16 + length) to skip the entire PROXY Protocol header (including TLV fields) and directly return the application data.

This workaround allows Cloud Provider A's MQTT connections to work, but it bypasses TLV parsing entirely, which means TLV metadata is lost.

Report Date: November 26, 2025 Reporter: nick

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions