[ 
https://issues.apache.org/jira/browse/CAMEL-23070?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen updated CAMEL-23070:
--------------------------------
    Priority: Minor  (was: Major)

> 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: Minor
>
> 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)

Reply via email to