IIS ARR Reverse Proxy Configuration Error 502.3

#1

What I am trying to do:
Enable access to the node-red editor hosted on a VM through the web using IIS as a reverse proxy.

The node-red editor is accessible through the reverse proxy, but displays "Lost connection to server, reconnecting in ..." and throws WebSocket handshake errors (reverse proxy returns 502.3).

if connected to the VM directly, the node-red editor works as expected

Without any luck I have been trying to figure out how to correctly configure my reverse proxy. Hopefully someone here can help me out :grinning:

The setup I am using:
NodeRed: Ubuntu 18.04 w/ node-red
ReverseProxy: Windows Server 2016 w/ IIS 10.0, ARR 3.0

IIS / ARR Config (parts of):
rewrite
    globalRules
        rule name="Force HTTPS" enabled="true" stopProcessing="true"
            match url="(.*)" 
            conditions
                add input="{HTTPS}" pattern="^OFF$" 
            conditions
            action type="Redirect" url="https:{HTTP_HOST}{R:1}" 
        rule
    globalRules
rewrite
proxy
	enabled="true"
	httpVersion="PassThrough"
	keepAlive="false"
	timeout="00:06:00"
	reverseRewriteHostInResponseHeaders="true"
	xForwardedByHeader=""
	includePortInXForwardedFor="false"
proxy
Site / URL Rewrite config:
?xml version="1.0" encoding="UTF-8"?
configuration
    system.webServer
        rewrite
            outboundRules
                rule name="NodeRed_Outbound" preCondition="ResponseIsHtml1" enabled="true"
                    match filterByTags="A, Area, Base, Form, Frame, Head, IFrame, Img, Input, Link, Script" pattern="^http(s)?://{VM domain removed}:1880/(.*)" 
                    action type="Rewrite" value="http{R:1}://{IIS}/{R:2}" 
                rule
                preConditions
                    preCondition name="ResponseIsHtml1"
                        add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" 
                    preCondition
                preConditions
            outboundRules
            rules
                rule name="NodeRed_Inbound" enabled="true" stopProcessing="true"
                    match url="(.*)" 
                    action type="Rewrite" url="http://{VM domain removed}:1880/{R:1}" 
                    conditions
                        add input="{HTTP_HOST}" pattern=".*{IIS subdomain removed}\.{IIS domain removed}\.{IIS toplevel domain removed}" 
                        add input="{CACHE_URL}" pattern="^(.+)://" 
                    conditions
                    serverVariables
                    serverVariables
                rule
            rules
        rewrite
        staticContent
            clientCache cacheControlMode="NoControl" 
        staticContent
        httpProtocol allowKeepAlive="false"
            customHeaders
                add name="Strict-Transport-Security" value="max-age=63072000; includeSubdomains" 
                add name="X-Content-Type-Options" value="nosniff" 
                add name="Referrer-Policy" value="no-referrer" 
                add name="X-XSS-Protection" value="1; mode=block" 
                add name="X-Robots-Tag" value="none" 
                add name="X-Download-Options" value="noopen" 
                add name="X-Permitted-Cross-Domain-Policies" value="none" 
            customHeaders
        httpProtocol
        security
            requestFiltering allowDoubleEscaping="true"
                requestLimits maxAllowedContentLength="2000000000" 
            requestFiltering
        security
    system.webServer
configuration

Some details and logs:
Node-red editor shows:

Lost connection to server, reconnecting in ...

Browser console log shows:

WebSocket connection to 'wss://{removed domain}/comms' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET

node-red audit log:

0|node-red | 12 Dec 20:02:07 - [audit] {"event":"comms.open","level":98,"timestamp":1544641327139}

freb log:

Summary
Url	https://(domain removed):443/comms
App Pool	{removed}
Authentication	anonymous
User from token	NT-AUTORIT√ĄT\IUSR
Activity ID	{8000006E-0003-D200-B63F-84710C7967BB}
Site	xx
Process	11744
Failure Reason	STATUS_CODE
Trigger Status	101
Final Status	502.3
Details
GENERAL_REQUEST_HEADERS:
Headers="
	Cache-Control: no-cache
	Connection: Upgrade
	Pragma: no-cache
	Upgrade: websocket
	Accept-Encoding: gzip, deflate, br
	Accept-Language: en-US,en;q=0.9
	Cookie: _ga=GA1.2.978382240.1544564967; _gid=GA1.2.1401031310.1544564967
	Host: {domain removed}
	User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
	Origin: https://{domain removed}
	Sec-WebSocket-Version: 13
	Sec-WebSocket-Key: /Ae4mACNf3sBlkYJZftrHA==
	Sec-WebSocket-Extensions: permessage-deflate;
	client_max_window_bits "

GENERAL_RESPONSE_HEADERS:
Headers="
	Upgrade: websocket
	Sec-WebSocket-Accept: oEMCEPAq+xLfe6s9i4xTr9PyZoY=
	Sec-WebSocket-Extensions: permessage-deflate
	X-Powered-By: ARR/3.0
	Connection: Upgrade
	X-Powered-By: ASP.NET
	Strict-Transport-Security: max-age=63072000;includeSubdomains
	X-Content-Type-Options: nosniff
	Referrer-Policy: no-referrer
	X-XSS-Protection: 1;mode=block
	X-Robots-Tag: none
	X-Download-Options: noopen
	X-Permitted-Cross-Domain-Policies: none"

GENERAL_FLUSH_RESPONSE_END:
BytesSent="0", ErrorCode="The parameter is incorrect. (0x80070057)"

MODULE_SET_RESPONSE_ERROR_STATUS:
ModuleName	ApplicationRequestRouting
Notification	EXECUTE_REQUEST_HANDLER
HttpStatus	502
HttpReason	Bad Gateway
HttpSubStatus	3
ErrorCode	The parameter is incorrect.
 (0x80070057)
ConfigExceptionInfo	

SET_RESPONSE_ERROR_DESCRIPTION:
ErrorDescription	There was a connection error while trying to route the request.
#2

You need to also proxy websockets not just HTTP. Sorry, I don't use IIS so I can't help you configure it though.

#3

Did you manage to make it work? I am going crazy hover this, tried everything but WS just keeps being disconnected by the IIS proxy....