I have a node.js socket.io server application that I have just moved to IISNode in IIS 8.5 in Windows Server 2012. It is set up to use https.
It all works fine when I browse locally but when I try to access it with a full domain name, I get error 403 (forbidden) when I try to open the web socket connection.
The same problem happens with my real application as happens with the Dante Devine Comedy socket.io sample. Tomasz Janczuk iisnode Dante sample
The standard sample when browsed to with
https://localhost/dante/server-socketio.js
or with
https://interfaces.xxxxxx.co.uk/enable/testing/dante/server-socketio.js
locally on the same server, opens the socket.io web socket connection with
var client = io.connect('https://localhost', { resource: 'dante/socket.io' });
and works correctly producing the following network capture:
Obviously the above does not work when accessed externally (not localhost) so I change the web socket connection to
var client = io.connect('https://interfaces.xxxxxx.co.uk/enable/testing',
{ resource: 'dante/socket.io' });
and this fails with an error 403 as follows:
my web.config is the same as the one supplied with the Dante sample and contains:
<handlers>
<add name="iisnode-socketio" path="server-socketio.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="LogFile" patternSyntax="ECMAScript">
<match url="socket.io"/>
<action type="Rewrite" url="server-socketio.js"/>
</rule>
</rules>
</rewrite>
<webSocket enabled="false" />
I'm new to node.js, socket.io and iisnode and a bit of a novice with IIS so this could be a simple iis/web site/https problem and not related to iisnode.
I'd appreciate it if anyone has any suggestions.
John.
Following CuriousGuy's suggestion, I now get the following network capture showing that the switch to web socket protocol has not happened. The actual error shown is
WebSocket connection to 'wss://interfaces.xxxxxx.co.uk/enable/testing/dante/socket.io/1/websocket/ANNcSf7ghQp66nwSS-7P'
failed: Error during WebSocket handshake: Unexpected response code: 200
I tried changing the server io.set from
io.set('resource', '/dante/socket.io');
to
io.set('resource', '/enable/testing/dante/socket.io');
but that was clearly a mistake because I then get an error that io is undefined which seems a little weird.
If I examine the network traffic in fiddler I see:
and the following error message in fiddler when I tap the last network line:
iisnode encountered an error when processing the request.
HRESULT: 0x6d
HTTP status: 500
HTTP reason: Internal Server Error
You are receiving this HTTP 200 response because
system.webServer/iisnode/#devErrorsEnabled
configuration setting is 'true'.
The server stderr log shows:
debug: served static content /socket.io.js
debug: client authorized
info: handshake authorized o7WE52TfMWPxFoJIZFJJ
debug: setting request GET /dante/socket.io/1/websocket/o7WE52TfMWPxFoJIZFJJ
debug: set heartbeat interval for client o7WE52TfMWPxFoJIZFJJ
warn: websocket connection invalid
info: transport end (undefined)
debug: set close timeout for client o7WE52TfMWPxFoJIZFJJ
debug: cleared close timeout for client o7WE52TfMWPxFoJIZFJJ
debug: cleared heartbeat interval for client o7WE52TfMWPxFoJIZFJJ
Related
I am using Express and HPM to proxy all requests to my website. This is all wrapped together into a little tool I call ws-proxy (ws for web server, not websocket).
One of the things proxied is my PVE/Proxmox Virtual Environment node, which uses secure WebSockets for the xterm.js and NoVNC consoles.
ws-proxy mre
What is weird about this, is after starting ws-proxy, I have about 30 seconds to open a console which will be sustained, but connections after this time will be closed with a 404 Not Found error. In the console, I see
[HPM] Upgrading to WebSocket
[HPM] Upgrading to WebSocket (sometimes up to 4 times)
[HPM] Client disconnected
In my browser, I see the connection returned as 404.
With websocat, I get:
websocat: WebSocketError: Received unexpected status code (404 Not Found)
websocat: error running
After additional debugging, I see something in the stack is sending a 404 and closing the connection, where just afterwards PVE sends the 101 Switching Protocols. This also sometimes causes a write after end error, sometimes socket hangup.
I've spent months looking into this and I have nowhere else to look at this point.
http-proxy-middleware#826 (by me)
404 in inspect element:
error log in console after a recent attempt (error will change)
Full list of steps between client and server:
Cloudflare
DigitalOcean w/ ssh-forward (not the problem)
ws-proxy
server
Non-websocket (HTTP) requests work fine. This is with HPM v2 and Node.js v16.
Update 1
After Ryker's answer, I attempted the solution which should have fixed it, but I see something else of concern after setting the logLevel to debug:
0|ws-proxy | pve.internal.0xlogn.dev ::1 - - [02/Nov/2022:23:17:14 +0000] "POST /api2/json/nodes/proxmox/lxc/105/termproxy HTTP/1.1" 200 487 "https://pve.internal.0xlogn.dev/?console=lxc&vmid=105&node=proxmox&resize=scale&xtermjs=1" "Mozilla/5.0 (X11; Linux x86_64; rv:106.0) Gecko/20100101 Firefox/106.0"
0|ws-proxy | Upgrade request for vhost pve.internal.0xlogn.dev, proxy out
0|ws-proxy | [HPM] GET /api2/json/nodes/proxmox/lxc/105/vncwebsocket?port=5900&vncticket=REDACTED -> https://10.0.1.2:8006
0|ws-proxy | [HPM] GET /api2/json/nodes/proxmox/lxc/105/vncwebsocket?port=5900&vncticket=REDACTED -> http://10.0.1.108:80
0|ws-proxy | [HPM] Upgrading to WebSocket
0|ws-proxy | [HPM] Upgrading to WebSocket
0|ws-proxy | [HPM] Client disconnected
0|ws-proxy | [HPM] GET /api2/json/cluster/resources -> https://10.0.1.2:8006
Notice the two GET requests? Something is duplicating the request.
My 'upgrade' event listener:
httpsServer.on('upgrade', (req, socket, head) => {
if (!req.headers.host) {
console.log('No vhost specified in upgrade request. Ignoring.');
socket.end();
return;
} else {
console.log(`Upgrade request for vhost ${req.headers.host}, proxy out`);
vhostProxyMiddlewareList[req.headers.host].upgrade(req, socket, head);
}
})
What's even weirder here, is after restarting, I get a short time where the request isn't duplicated. Plus, there is a normal HTTP request anyway.
Update 2
After noticing the dual requests, I believe it is possible the module vhost is causing a weird wildcard and sending the request to two target nodes. I will update shortly.
Update 3
After further work I believe this is true. However, vhost is not at fault, rather something is implicitly calling next().
Update 4
This is still an issue, even after multiple attempts at changing this. I have not heard anything back from HPM.
http-proxy-middleware relies on a initial http request in order to listen to the http upgrade event by default. To proxy WebSockets without the initial http request, you can subscribe to the server's http upgrade event manually.
Add this listener to your http server
const wsProxy = createProxyMiddleware({ target: targetURL, onError, ...PROXY_DEFAULT_OPTIONS, ...addlProxyOptions });
httpsServer.on('upgrade', wsProxy.upgrade); // <-- subscribe to http 'upgrade'
I am trying to configure https to my website hosted on IIS on a Windows Server 2012. My project is a default WebApi application from ASP.NET Core 2.1 and I am using win-acme to configure IIS with a Let’s Encrypt certificate.
Everything runs fine besides the fact that http traffic is not being redirected to https. If I check the logs, I get:
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
I thought that this could be easily solved by adding this to my ConfigureServices method:
services.AddHttpsRedirection(options =>
{
options.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
options.HttpsPort = 443;
});
However, now I can’t access my website at all. Chrome gives me a message:
This page isn't working www.example.com redirected you too many times
If I check the logs it shows me a bunch of lines like this:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://example.com
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.1026ms 307
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://example.com
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 0.1837ms 307
Does anyone have any idea what I am doing wrong?
I just found out the answer. This can be solved by adding the following code to ConfigureServices.cs:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
Source: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1#forwarded-headers-middleware-options
Deployed ASP.NET MVC Core 1.1.1 on Windows 2012 Server R2. Followed this ASP.NET article (installed DotNetCore.1.0.5_1.1.2-WindowsHosting bundle etc). App runs fine as localhost on the server if we follow the following steps:
In cmd from root dir of the app, ran: dotnet MyWebapplication.dll
Noticed that application is running and waiting for responses on localhost:5000.
Opened the browser on the host server and navigated to: http://localhost:5000
Home page opened as expected
But when we navigate to the http://IP Address/MyWebapplication on a different desktop on the same network, we get the 500 - Internal Server Error
NOTE: We tested that if we host a simple web app (not ASP.NET Core) with just one Index.html page on IIS, we can access the app from another machine on the same network via, say, http://IP Address/MySimpleHtmlApp. So issue seems to be related to something on ASP.NET Core deployment on IIS. Question: What we may be missing and how to resolve it?
UPDATE:
The IIS has default port 80 that is open. When we run the app directly from IIS on the server (i.e., http://localhost:80/MyWebapplication) it gives the following error:
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Detailed Error Information:
Module IIS Web Core
Notification BeginRequest
Handler Not yet determined
Error Code 0x8007000d
Config Error
Config File \\?\D:\TestApp\PublishOutput\web.config
Requested URL http://localhost:80/TestWebApp
Physical Path D:\TestApp\PublishOutput
Logon Method Not yet determined
Logon User Not yet determined
Config Source:
-1:
0:
Following is the web.config file (created by VS2017):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\TestWebApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
<!--ProjectGuid: 21c38c6d-7aff-4624-b310-a0f5f766b461-->
Well, first off, you're not really deploying this to IIS; you're self-hosting. If you want to run it under IIS, you need to create a site in IIS for it, drop in the published code, and configure the App Pool to run "No Managed Code". Then, you can pull up the site under whatever bindings you've added for it in IIS.
Second, your test case of a "simple website", it not utilizing a non-standard web port (it's using 80), while your ASP.NET Core app is (5000). This may very well be due to a firewall you have running, as most firewall appliances will block access by default to any non-standard port. You'll either need to open up a rule for that port on your firewall or host it on port 80, like you're doing with your "simple website".
I'm running a Node.JS application in the subdomain of WP site. The WP site itself is running on Nginx, php-fpm and Varnish and works just fine, so I'm using Nginx to proxy connections to the Node app.
With Firefox, the Node app works perfectly. The home page and every other page loads, including the admin end. However, on Chromium, the site does not load properly. If I attempt to view the home page, the main content area loads, but the sidebar does not. And I get the following message in the Web console:
WebSocket connection to 'ws://forum.site.com/socket.io/1/websocket/91qNR-mt333a'
failed: Unexpected response code: 502
In the Nginx log file, I see entries like:
2089 upstream prematurely closed connection while reading response header from upstream,
client: 127.0.0.1, server: forum.site.com, request: "GET /socket.io/1/websocket/91qNR-
mt333a HTTP/1.1", upstream: "http://127.0.0.1:4567/socket.io/1/websocket/91qNRaWZ3-
mt333a", host: "forum.site.com"
And if I try to navigate between posts on the site, I get these messages in the Web console:
Failed to load resource: the server responded with a status of 504 (Gateway Time-out)
http://forum.site.com/socket.io/1/xhr-polling/91qNRaWZ3rYcF-mt333a?t=1396434040701
Then these lines from Nginx error log:
2128 upstream timed out (110: Connection timed out) while reading response header from
upstream, client: 127.0.0.1, server: forum.site.com, request: "GET /socket.io/1/xhr-
polling/uH9QTAWUGmomqFoy333e?t=1396434162051 HTTP/1.1", upstream:
"http://127.0.0.1:4567/socket.io/1/xhr-polling/uH9QTAWUGmomqFoy333e?t=1396434162051",
host: "forum.site.com", referrer: "http://forum.site.com/category/35/dual-boots"
I've looked at similar issues on this site and other sites and tried to implement the suggested solutions, but no luck so far. For example, in the Nginx config for the subdomain, I've added the following:
proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_connect_timeout 120;
proxy_read_timeout 300;
And played around with different values for the last two lines, but still no luck.
What baffles me is that the site works perfectly on FF. It's only on Chromium that I'm having these problem. I've not tried on IE, but I'm not really concerned about that browser at this point.
I'm sure there's something that I'm overlooking, but I don't know what.
Btw, the site exhibits the same behavior on Android's default browser.
Could Varnish be the culprit here. I have Varnish (port 80) in front of Nginx (8080). Does Varnish play nice with WebSockets?
Finally figured out that the problem is with Varnish, which by default does not handle WebSocket traffic. It has to be explicitly configured for it.
See this link for the solution.
This seems to be a common problem but I've troubleshot all the other techniques people are getting and had no luck, so here goes:
I'm running WebAPI2 along with IIS7.5 on Windows Server 2010. In development my PUT/DELETE requests started working after I added the PUT/DELETE Handlers in HTTP Handlers of IIS. However, once I rolled to prod and applied the same changes I got no such luck. Heres my setup:
WebConfig
Server:
Requests:
Request URL:http://dev.myserver.com/myapp/api/apps/76a09a7b-0750-4045-a3ce-696df0ff179c
Request Method:PUT
Status Code:405 Method Not Allowed
405 - HTTP verb used to access this page is not allowed.
The page you are looking for cannot be displayed because an invalid method (HTTP verb) was used to attempt access.
Response Headers:
Allow:GET, HEAD, OPTIONS, TRACE
Content-Length:1293
Content-Type:text/html
Date:Thu, 21 Nov 2013 15:43:44 GMT
Server:Microsoft-IIS/7.5
X-Powered-By:ASP.NET
Obliviously its mad because that verb is not acceptable but the configuration shows that it is. I saw another article talking about removing the WebDav Module from the Modules in IIS, however, once I did that I got a 500 Internal Server Error ( probably because its needed hehe ). Like I said this code is working correctly in dev so I'm not sure what the disconnect is.
Seems if I missed the 'HttpHandler' remove of WebDav. The following works:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>