[
https://issues.apache.org/jira/browse/CAMEL-23070?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Reto Peter updated CAMEL-23070:
-------------------------------
Description:
The async MDN receiver ({{{}AS2AsyncMDNServerConnection{}}}) uses
{{RequestValidateHost}} in its HttpProcessor, which enforces strict host header
validation per HttpCore 5.3+. This causes incoming async MDN requests to be
rejected with HTTP 421 "Not authoritative"
when the {{Host}} header doesn't exactly match the server's expected
hostname.
The main AS2 receiver ({{{}AS2ServerConnection{}}}) does not use
{{{}RequestValidateHost{}}}, so it accepts any {{Host}} header. This is an
inconsistency — async MDNs are rejected while regular AS2 messages are accepted.
\{panel}
h3. Root Cause
In {{AS2AsyncMDNServerConnection.RequestListenerThread}} constructor (line
~105):
\{code:java|title=AS2AsyncMDNServerConnection.java (Camel 4.18.0)}
public RequestListenerThread(int port, SSLContext sslContext) throws
IOException
{ setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port); // ...
HttpProcessor httpProcessor = new DefaultHttpProcessor(new
RequestValidateHost()); // <-- STRICT registry = new
RequestHandlerRegistry<>(); handler = new
BasicHttpServerRequestHandler(registry); httpService = new
HttpService(httpProcessor, handler); }
\{code}
But in {{AS2ServerConnection.initProtocolProcessor()}} (line ~655):
\{code:java|title=AS2ServerConnection.java (Camel 4.18.0)}
protected HttpProcessor initProtocolProcessor(
String as2Version, String originServer, String serverFqdn, String
mdnMessageTemplate)
{ return HttpProcessorBuilder.create() .addFirst(new
AS2ConsumerConfigInterceptor()) .add(new ResponseContent(true))
.add(new ResponseServer(originServer)) .add(new
ResponseDate()) .add(new ResponseConnControl())
.add(new ResponseMDN(as2Version, serverFqdn, mdnMessageTemplate))
.build(); // <-- NO
RequestValidateHost }
\{code}
The main AS2 server uses {{HttpProcessorBuilder}} with response interceptors
only — no {{{}RequestValidateHost{}}}. The async MDN server uses
{{DefaultHttpProcessor}} with only {{RequestValidateHost}} and no response
interceptors at all.
h3. Impact
- Partners that send async MDNs with a {{Host}} header that doesn't match the
server's configured hostname get HTTP 421 "Not authoritative"
- This is common in production environments with load balancers, reverse
proxies, or NAT where the external hostname differs from the internal one
- The sender thinks the MDN delivery failed and may retry or flag the
transmission as unconfirmed
- Meanwhile, the original AS2 message was received successfully (because
{{AS2ServerConnection}} has no host validation)
h3. Steps to Reproduce
Configure a Camel AS2 server with async MDN enabled on a separate port
Have a partner send an AS2 message requesting async MDN delivery
Partner sends the async MDN to the callback URL
If the {{Host}} header in the MDN request doesn't exactly match the server's
hostname: HTTP 421 "Not authoritative"
This is easy to trigger in environments with:
- Load balancers or reverse proxies (external hostname differs from internal)
- Docker/Kubernetes (container hostname differs from service hostname)
- NAT configurations
- Partners that set {{Host}} header to the IP address instead of the hostname
h3. Proposed Fix
Remove {{RequestValidateHost}} from the async MDN server and add the same
response interceptors as the main AS2 server:
\{code:diff|title=Fix in AS2AsyncMDNServerConnection.java}
public RequestListenerThread(int port, SSLContext sslContext) throws
IOException
{ setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port); // ... -
HttpProcessor httpProcessor = new DefaultHttpProcessor(new
RequestValidateHost()); - HttpProcessor httpProcessor =
HttpProcessorBuilder.create() .add(new ResponseContent(true))
.add(new ResponseDate()) .add(new ResponseServer(null))
.add(new ResponseConnControl()) .build(); - registry = new
RequestHandlerRegistry<>(); handler = new
BasicHttpServerRequestHandler(registry); httpService = new
HttpService(httpProcessor, handler); }
\{code}
This makes the async MDN receiver consistent with the main AS2 receiver:
- No strict host validation (same as {{{}AS2ServerConnection{}}})
- Standard response interceptors are added ({{{}ResponseContent{}}},
{{{}ResponseDate{}}}, etc.) — the current code has none, which means async MDN
responses may also be missing standard HTTP headers
h3. Additional Issue: Missing Response Interceptors
Note that the current {{AS2AsyncMDNServerConnection}} creates the
HttpProcessor with only {{RequestValidateHost}} and no response interceptors:
\{code:java}
HttpProcessor httpProcessor = new DefaultHttpProcessor(new
RequestValidateHost());
\{code}
This means HTTP responses from the async MDN receiver may be missing standard
headers like {{{}Content-Length{}}}, {{{}Date{}}}, and {{{}Connection{}}}. The
proposed fix addresses both issues.
h3. Our Workaround
We use reflection after endpoint initialization to replace the
{{HttpProcessor}} on the async MDN server's {{HttpService}} with a permissive
processor built via {{HttpProcessorBuilder}} (with standard response
interceptors but no {{{}RequestValidateHost{}}}).
h3. Test Scenario
Tested with OpenAS2 sending async MDNs.
Before fix: Async MDNs rejected with HTTP 421 when Host header doesn't match.
After replacing HttpProcessor: Async MDNs accepted regardless of Host header
value.
was:
The async MDN receiver (\{{AS2AsyncMDNServerConnection}}) uses
\{{RequestValidateHost}} in its HttpProcessor, which enforces strict host
header validation per HttpCore 5.3+. This causes incoming async MDN requests to
be rejected with HTTP 421 "Not authoritative"
when the \{{Host}} header doesn't exactly match the server's expected
hostname.
The main AS2 receiver (\{{AS2ServerConnection}}) does not use
\{{RequestValidateHost}}, so it accepts any \{{Host}} header. This is an
inconsistency — async MDNs are rejected while regular AS2 messages are accepted.
\{panel}
h3. Root Cause
In \{{AS2AsyncMDNServerConnection.RequestListenerThread}} constructor (line
~105):
\{code:java|title=AS2AsyncMDNServerConnection.java (Camel 4.18.0)}
public RequestListenerThread(int port, SSLContext sslContext) throws
IOException {
setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port);
// ...
HttpProcessor httpProcessor = new DefaultHttpProcessor(new
RequestValidateHost()); // <-- STRICT
registry = new RequestHandlerRegistry<>();
handler = new BasicHttpServerRequestHandler(registry);
httpService = new HttpService(httpProcessor, handler);
}
\{code}
But in \{{AS2ServerConnection.initProtocolProcessor()}} (line ~655):
\{code:java|title=AS2ServerConnection.java (Camel 4.18.0)}
protected HttpProcessor initProtocolProcessor(
String as2Version, String originServer, String serverFqdn, String
mdnMessageTemplate) {
return HttpProcessorBuilder.create()
.addFirst(new AS2ConsumerConfigInterceptor())
.add(new ResponseContent(true))
.add(new ResponseServer(originServer))
.add(new ResponseDate())
.add(new ResponseConnControl())
.add(new ResponseMDN(as2Version, serverFqdn, mdnMessageTemplate))
.build();
// <-- NO RequestValidateHost
}
\{code}
The main AS2 server uses \{{HttpProcessorBuilder}} with response interceptors
only — no \{{RequestValidateHost}}. The async MDN server uses
\{{DefaultHttpProcessor}} with only \{{RequestValidateHost}} and no response
interceptors at all.
h3. Impact
- Partners that send async MDNs with a \{{Host}} header that doesn't match
the server's configured hostname get HTTP 421 "Not authoritative"
- This is common in production environments with load balancers, reverse
proxies, or NAT where the external hostname differs from the internal one
- The sender thinks the MDN delivery failed and may retry or flag the
transmission as unconfirmed
- Meanwhile, the original AS2 message was received successfully (because
\{{AS2ServerConnection}} has no host validation)
h3. Steps to Reproduce
Configure a Camel AS2 server with async MDN enabled on a separate port
Have a partner send an AS2 message requesting async MDN delivery
Partner sends the async MDN to the callback URL
If the \{{Host}} header in the MDN request doesn't exactly match the server's
hostname: HTTP 421 "Not authoritative"
This is easy to trigger in environments with:
- Load balancers or reverse proxies (external hostname differs from internal)
- Docker/Kubernetes (container hostname differs from service hostname)
- NAT configurations
- Partners that set \{{Host}} header to the IP address instead of the hostname
h3. Proposed Fix
Remove \{{RequestValidateHost}} from the async MDN server and add the same
response interceptors as the main AS2 server:
\{code:diff|title=Fix in AS2AsyncMDNServerConnection.java}
public RequestListenerThread(int port, SSLContext sslContext) throws
IOException {
setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port);
// ...
- HttpProcessor httpProcessor = new DefaultHttpProcessor(new
RequestValidateHost());
- HttpProcessor httpProcessor = HttpProcessorBuilder.create()
.add(new ResponseContent(true))
.add(new ResponseDate())
.add(new ResponseServer(null))
.add(new ResponseConnControl())
.build();
- registry = new RequestHandlerRegistry<>();
handler = new BasicHttpServerRequestHandler(registry);
httpService = new HttpService(httpProcessor, handler);
}
\{code}
This makes the async MDN receiver consistent with the main AS2 receiver:
- No strict host validation (same as \{{AS2ServerConnection}})
- Standard response interceptors are added (\{{ResponseContent}},
\{{ResponseDate}}, etc.) — the current code has none, which means async MDN
responses may also be missing standard HTTP headers
h3. Additional Issue: Missing Response Interceptors
Note that the current \{{AS2AsyncMDNServerConnection}} creates the
HttpProcessor with only \{{RequestValidateHost}} and no response interceptors:
\{code:java}
HttpProcessor httpProcessor = new DefaultHttpProcessor(new
RequestValidateHost());
\{code}
This means HTTP responses from the async MDN receiver may be missing standard
headers like \{{Content-Length}}, \{{Date}}, and \{{Connection}}. The proposed
fix addresses both issues.
h3. Our Workaround
We use reflection after endpoint initialization to replace the
\{{HttpProcessor}} on the async MDN server's \{{HttpService}} with a permissive
processor built via \{{HttpProcessorBuilder}} (with standard response
interceptors but no \{{RequestValidateHost}}).
h3. Test Scenario
Tested with OpenAS2 sending async MDNs.
Before fix: Async MDNs rejected with HTTP 421 when Host header doesn't match.
After replacing HttpProcessor: Async MDNs accepted regardless of Host header
value.
> AS2AsyncMDNServerConnection uses strict RequestValidateHost — async MDNs
> rejected with HTTP 421
> -----------------------------------------------------------------------------------------------
>
> Key: CAMEL-23070
> URL: https://issues.apache.org/jira/browse/CAMEL-23070
> Project: Camel
> Issue Type: Bug
> Components: camel-as2
> Affects Versions: 4.18.0
> Reporter: Reto Peter
> Priority: Major
>
> The async MDN receiver ({{{}AS2AsyncMDNServerConnection{}}}) uses
> {{RequestValidateHost}} in its HttpProcessor, which enforces strict host
> header validation per HttpCore 5.3+. This causes incoming async MDN requests
> to be rejected with HTTP 421 "Not authoritative"
> when the {{Host}} header doesn't exactly match the server's expected
> hostname.
> The main AS2 receiver ({{{}AS2ServerConnection{}}}) does not use
> {{{}RequestValidateHost{}}}, so it accepts any {{Host}} header. This is an
> inconsistency — async MDNs are rejected while regular AS2 messages are
> accepted.
> \{panel}
> h3. Root Cause
> In {{AS2AsyncMDNServerConnection.RequestListenerThread}} constructor (line
> ~105):
> \{code:java|title=AS2AsyncMDNServerConnection.java (Camel 4.18.0)}
> public RequestListenerThread(int port, SSLContext sslContext) throws
> IOException
> { setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port); // ...
> HttpProcessor httpProcessor = new DefaultHttpProcessor(new
> RequestValidateHost()); // <-- STRICT registry = new
> RequestHandlerRegistry<>(); handler = new
> BasicHttpServerRequestHandler(registry); httpService = new
> HttpService(httpProcessor, handler); }
> \{code}
> But in {{AS2ServerConnection.initProtocolProcessor()}} (line ~655):
> \{code:java|title=AS2ServerConnection.java (Camel 4.18.0)}
> protected HttpProcessor initProtocolProcessor(
> String as2Version, String originServer, String serverFqdn, String
> mdnMessageTemplate)
> { return HttpProcessorBuilder.create() .addFirst(new
> AS2ConsumerConfigInterceptor()) .add(new ResponseContent(true))
> .add(new ResponseServer(originServer)) .add(new
> ResponseDate()) .add(new ResponseConnControl())
> .add(new ResponseMDN(as2Version, serverFqdn, mdnMessageTemplate))
> .build(); // <--
> NO RequestValidateHost }
> \{code}
> The main AS2 server uses {{HttpProcessorBuilder}} with response
> interceptors only — no {{{}RequestValidateHost{}}}. The async MDN server uses
> {{DefaultHttpProcessor}} with only {{RequestValidateHost}} and no response
> interceptors at all.
> h3. Impact
> - Partners that send async MDNs with a {{Host}} header that doesn't match
> the server's configured hostname get HTTP 421 "Not authoritative"
> - This is common in production environments with load balancers, reverse
> proxies, or NAT where the external hostname differs from the internal one
> - The sender thinks the MDN delivery failed and may retry or flag the
> transmission as unconfirmed
> - Meanwhile, the original AS2 message was received successfully (because
> {{AS2ServerConnection}} has no host validation)
> h3. Steps to Reproduce
> Configure a Camel AS2 server with async MDN enabled on a separate port
> Have a partner send an AS2 message requesting async MDN delivery
> Partner sends the async MDN to the callback URL
> If the {{Host}} header in the MDN request doesn't exactly match the
> server's hostname: HTTP 421 "Not authoritative"
> This is easy to trigger in environments with:
> - Load balancers or reverse proxies (external hostname differs from
> internal)
> - Docker/Kubernetes (container hostname differs from service hostname)
> - NAT configurations
> - Partners that set {{Host}} header to the IP address instead of the
> hostname
> h3. Proposed Fix
> Remove {{RequestValidateHost}} from the async MDN server and add the same
> response interceptors as the main AS2 server:
> \{code:diff|title=Fix in AS2AsyncMDNServerConnection.java}
> public RequestListenerThread(int port, SSLContext sslContext) throws
> IOException
> { setName(REQUEST_LISTENER_THREAD_NAME_PREFIX + port); // ...
> - HttpProcessor httpProcessor = new DefaultHttpProcessor(new
> RequestValidateHost()); - HttpProcessor httpProcessor =
> HttpProcessorBuilder.create() .add(new ResponseContent(true))
> .add(new ResponseDate()) .add(new ResponseServer(null))
> .add(new ResponseConnControl()) .build(); - registry = new
> RequestHandlerRegistry<>(); handler = new
> BasicHttpServerRequestHandler(registry); httpService = new
> HttpService(httpProcessor, handler); }
> \{code}
> This makes the async MDN receiver consistent with the main AS2 receiver:
> - No strict host validation (same as {{{}AS2ServerConnection{}}})
> - Standard response interceptors are added ({{{}ResponseContent{}}},
> {{{}ResponseDate{}}}, etc.) — the current code has none, which means async
> MDN responses may also be missing standard HTTP headers
> h3. Additional Issue: Missing Response Interceptors
> Note that the current {{AS2AsyncMDNServerConnection}} creates the
> HttpProcessor with only {{RequestValidateHost}} and no response interceptors:
> \{code:java}
> HttpProcessor httpProcessor = new DefaultHttpProcessor(new
> RequestValidateHost());
> \{code}
> This means HTTP responses from the async MDN receiver may be missing
> standard headers like {{{}Content-Length{}}}, {{{}Date{}}}, and
> {{{}Connection{}}}. The proposed fix addresses both issues.
> h3. Our Workaround
> We use reflection after endpoint initialization to replace the
> {{HttpProcessor}} on the async MDN server's {{HttpService}} with a permissive
> processor built via {{HttpProcessorBuilder}} (with standard response
> interceptors but no {{{}RequestValidateHost{}}}).
> h3. Test Scenario
> Tested with OpenAS2 sending async MDNs.
> Before fix: Async MDNs rejected with HTTP 421 when Host header doesn't
> match.
> After replacing HttpProcessor: Async MDNs accepted regardless of Host
> header value.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)