HTTPS and iisnode - node.js

I'm using node in combination with IIS by using iisnode.
I seems to me that things that I was previously doing in Node to configure the server can now be done directly in IIS.
Things like:
https configuration (and certificates)
http to https redirection
Does this mean I can get rid of the node code that did that and go just for the IIS method?
var fs = require('fs');
var https = require('https');
var options = {
key: fs.readFileSync('./ssl/xxxxxxx.private.pem'),
cert: fs.readFileSync('./ssl/xxxxxxx.public.pem'),
};
https.createServer(options, app).listen(443);

Your keys and pfx should never live on the file system. One slip up could serve your files to the internet and now everyone can get your key. Storing them in the windows cert store is best.
Yes. You should do all the ssl configuration on IIS and Windows.
This is what I have used on production.
On the application, you should simply write:
var app = express();
app.listen(process.env.port);
Then web.config for iisnode should look like this:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="HTTP to Prod HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
<!-- Don't interfere with requests for logs -->
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$" />
</rule>
<!-- Don't interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}" />
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
</conditions>
<action type="Rewrite" url="app.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Related

How can I use IIS URL Rewrite to forward http to https node.js app?

I am using URL rewrite to redirect all incoming request to my node.js app.
It works fine.
However, I want to redirect
http://www.example.com
to
https://www.example.com
I have googled the related setting.
Although, it can display the node.js web app correctly, however, the browser report that is not a secure web site.
Here is my web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="forward rule" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://localhost:9000/{R:1}" />
</rule>
<rule name="http to https" enabled="true" stopProcessing="true">
<match url="(.*)" />
<conditions trackAllCaptures="true">
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://www.example.com" />
</rule>
</rules>
</rewrite>
<httpRedirect enabled="false" destination="https://www.example.com/" exactDestination="false" childOnly="true" httpResponseStatus="Permanent" />
</system.webServer>
</configuration>
I found that if I don't bind HTTP to the web site, it will prompt error.

Azure rewrite rules causing error 404 in detailed logs

I have a website with the following structure at the root for a Node.js app
package.json
server.js
public
index.html
css
js
images
...other folders
I would like to take the person only inside the public folder with a forced HTTPS connection.
My current web.config file looks like this
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
<rule name="Force HTTPS" enabled="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
<rule name="Redirect rquests to default azure websites domain" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^zupbot\.azurewebsites\.net$" />
</conditions>
<action type="Redirect" url="https://www.zup.chat/{R:0}" />
</rule>
</rules>
</rewrite>
<!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<!--<iisnode watchedFiles="web.config;*.js"/>-->
</system.webServer>
</configuration>
Whenever I try to access my website, it tries finding a server.js and gives me this error
{"code":"NotAuthorized","message":"/server.js"}
My node.js code does this to serve static files
server.get('/.*/', restify.serveStatic({
//Ensure that people can only access the files within the public directory and none of the protected server files
directory: __dirname + '/public',
default: constants.INDEX_HTML,
match: /^((?!server.js).)*$/ // we should deny access to the application source
}));
How can I take the person straight inside the public folder always with an HTTPS connection? Thank you for your help in advance.
UPDATE 1
I added the HTTPS redirect before any other rule that has a stopProcessing=true and it works , however if I go to my native site http://.azurewebsites.net, it still takes me to the https version of it, how can I redirect sitename.azurewebsites.net to the https version of my custom domain?
Please try the following rewrite rules in web.config:
<rule name="DynamicContent" stopProcessing="true">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
<rule name="Redirect to https" enabled="true" patternSyntax="ECMAScript" stopProcessing="true">
<match url="(.*)"/>
<conditions>
<add input="{HTTPS}" pattern="Off"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" />
</rule>
Which will rewrite the url your_site.azurewebsites.net/<asset> to https protocol if there is a file named <asset> in public folder as you configured in restify.serveStatic.
And it will not rewrite the url those can match the route setting in your restify application.
Any further concern, please feel free to let me know.

Why doesn't Nodejs app work on Windows IIS

I use nodejs app with express i want to host on windows IIS. On my IIS8 nodejs is working. but I got an error 'Cannot GET /node/server.js' and I put rewrite rules in web.config. then I got 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.
I discovered on internet. everyone suggest the following configuration but is not working on my windows
my web.config file is:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<defaultDocument>
<files>
<add value="server.js" />
</files>
</defaultDocument>
<rewrite>
<rules>
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$"/>
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<iisnode nodeProcessCountPerApplication="8" watchedFiles="*.js;node_modules\*;routes\*.js;views\*.html"/>
</system.webServer>
</configuration>
any suggestion?
Thanks
Your configuration file looks valid. So, you have to install iis rewrite extension and it works well.

Cannot Get Azure Node.js Logging Enabled

I am unable to get logging to work for a node application I am deploying to Windows Azure. I am overriding the web.config with the iisnode.yml file option.
Here's the yml file contents:
node_env: development
nodeProcessCountPerApplication: 1
maxConcurrentRequestsPerProcess: 1024
maxNamedPipeConnectionRetry: 24
namedPipeConnectionRetryDelay: 250
maxNamedPipeConnectionPoolSize: 512
maxNamedPipePooledConnectionAge: 30000
asyncCompletionThreadCount: 0
initialRequestBufferSize: 4096
maxRequestBufferSize: 65536
watchedFiles: *.js;iisnode.yml
uncFileChangesPollingInterval: 5000
gracefulShutdownTimeout: 60000
loggingEnabled: true
logDirectory: iisnode
debuggingEnabled: true
debuggerPortRange: 5058-6058
debuggerPathSegment: debug
maxLogFileSizeInKB: 128
maxTotalLogFileSizeInKB: 1024
maxLogFiles: 20
devErrorsEnabled: true
flushResponse: false
enableXFF: false
Here's the contents of the web.config file that's being overriden:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="false" />
<iisnode configOverrides="iisnode.yml" debuggingEnabled="true" loggingEnabled="true" logDirectory="iisnode" devErrorsEnabled="true" nodeProcessCommandLine=""%programfiles(x86)%\nodejs\node.exe"" />
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<clear />
<rule name="app" enabled="true" patternSyntax="ECMAScript" stopProcessing="true">
<match url="server\.js.+" negate="true" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="server.js" />
</rule>
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="iisnode"/>
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{{REQUEST_URI}}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{{REQUEST_FILENAME}}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I'm pretty sure I have enabled every logging option I can in both, but neither seems to be picked up by Azure during deployment and when I access the typical logging location, http://mysite.com/iisnode/index.html or http://mysite.com/iisnode/ I receive a 404 error.
Any help or ideas would be appreciated.
If you are using express add this under your static folder location
app.use(express.static(__dirname + '/../iisnode'));
Or define your own log routes like below.. here you can get fancy and only show errors etc.
//logging routes
var fs = require('fs');
app.get('/iisnode', function(req, res){
var _index = fs.readFileSync('./iisnode/index.html', 'utf8');
var index = _index.replace("logCell.innerHTML = 'log';", "logCell.innerHTML = 'log';");
res.send(index);
});
app.get('/iisnode/:log', function(req, res){
var _log = fs.readFileSync('./iisnode/' + req.route.params['log'], 'utf8');
res.contentType('text/plain');
res.send(_log);
});
You can replace the app.get with whatever routing solution you are using.
Remember to remove before launching the app in production.

Simple IIS URL Rewrite

Simple question. I need to redirect all http 80 and https 443 requests on a specific subdomain URL to an alternative SSL port https 444.
Example: http://sub.corp.com --> https://sub.corp.com:444
Example: https://sub.corp.com --> https://sub.corp.com:444
I only wish to use IIS 7.5 URL Rewrite module.
Thanks.
The following URL rewrite rule should do what you want:
<rewrite>
<rules>
<rule name="Redirect to port 444" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="^ON$" negate="true" />
<add input="{SERVER_PORT}" pattern="^444$" negate="true" />
</conditions>
<action type="Redirect" url="https://sub.corp.com:444/{R:0}" />
</rule>
</rules>
</rewrite>
It redirects to https://sub.corp.com:444 whenever HTTPS is not ON or when the port number is not 444. The site should have bindings to port 80 (with HTTP), 443 (with HTTPS for standards SSL) en 444 (with HTTPS) for this to work.
Marco's solutions works fine, in case somebody is wondering how to apply this in IIS.
you add this to the web.config file. If you create a Virtual Directory in IIS the selected physical folder will have a web.config created.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to port 50443" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTPS}" pattern="^ON$" negate="true" />
<add input="{SERVER_PORT}" pattern="^50443$" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}:50443/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

Resources