Using Nginx as a reverse proxy with persistent connections enabled, CWMP logs show "invalid session."

Using nginx as a reverse proxy with long connections enabled, the CWMP (CPE WAN Management Protocol) logs show “invalid session”.

When only a single device is connected, it works fine, but concurrency leads to “invalid session” errors. I’ve traced the code and found that the context is bound to the socket. Long connections between nginx and CWMP seem to be managed through a connection pool. When connections are idle, they can be assigned to other devices, leading to context mix-ups.

If long connections aren’t enabled, digest authentication fails to retrieve the corresponding token, resulting in unsuccessful authentication.

Do you have any elegant nginx configuration to share, or any other solutions?

my nginx.conf:

upstream CWMP_BACKEND {
    server   127.0.0.1:37547  weight=1 max_fails=2 fail_timeout=30s;
    keepalive 300;
}
server {
    listen 80;
    
    client_body_buffer_size 5m;
    
    location / {
        proxy_pass http://CWMP_BACKEND;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Using the latest version, hope someone can give me some guidance, thanks!

I think the general recommendation is to not proxy the cwmp traffic because of these kinds of issues. What are the reasons why you want to proxy the cwmp traffic?

We usually don’t want the external network traffic to be directly connected to our system, and we need to identify the connection to avoid malicious attacks. Only valid requests are forwarded to CWMP

look at this:

Does it work for you?

upstream CWMP_BACKEND {
    server   127.0.0.1:37547  weight=1 max_fails=2 fail_timeout=30s;
    keepalive 300;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

server {
    listen 80;
    
    client_body_buffer_size 5m;
    
    location / {
        proxy_pass http://CWMP_BACKEND;
        proxy_http_version 1.1;
        proxy_set_header Connection $connection_upgrade;  # Preserve Upgrade header for WebSocket connections
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_set_header X-Forwarded-Proto $scheme;  # Preserve original protocol if behind SSL termination
        proxy_set_header Upgrade $http_upgrade;      # Preserve Upgrade header for WebSocket connections
        proxy_read_timeout 300s;                     # Set a higher timeout for long connections
        proxy_send_timeout 300s;
        proxy_connect_timeout 75s;                   # Adjust timeout settings as necessary
        proxy_buffering off;                         # Disable buffering to prevent context mix-ups
    }
}
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;

The above configuration requires support for the WebSocket protocol to function properly. However, it cannot guarantee a keep-alive connection from Nginx to the CWMP service. Therefore, even when using digest authentication, authentication fails.

Currently, after reading the code, the reason for the failure is clear (the context and socket are deeply bound). However, I cannot find a method in Nginx to allow the client to exclusively occupy the socket connection from Nginx to CWMP. Perhaps I need to switch to a different proxy software?