Accessing Node.js app on Vagrant via SSL/TLS connection - javascript

So I inherited a Nodes.js app which I am running on a Vagrant box.
I have the app binding to "0.0.0.0", and it has its own server.key and certs in the securekey folder.
var https = require('https');
var fs = require('fs');
var ssl_options = {
key: fs.readFileSync('./securekey/server.key'),
cert: fs.readFileSync('./securekey/server.crt'),
ca: fs.readFileSync('./securekey/ca.crt')
};
https.createServer(ssl_options, app).listen(3001, '0.0.0.0');
When I run the app, I expected to be able to access it on my Windows (Vagrant is running on my Windows PC) browser via the URL https://localhost:3001
But I get "Secure Connection Failed" on Mozilla.
I did tried this on Windows pc using Cygwin:
$ openssl s_client -host 127.0.0.1 -port 3001
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 316 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1461923745
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
And
$ curl -v -k 'https://localhost:3001'
* STATE: INIT => CONNECT handle 0x6000574a0; line 1103 (connection #-5000)
* Rebuilt URL to: https://localhost:3001/
* Added connection 0. The cache now contains 1 members
* Trying 127.0.0.1...
* STATE: CONNECT => WAITCONNECT handle 0x6000574a0; line 1156 (connection #0)
* Connected to localhost (127.0.0.1) port 3001 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x6000574a0; line 1253 (connection #0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x6000574a0; line 1267 (connection #0)
* Unknown SSL protocol error in connection to localhost:3001
* Curl_done
* Closing connection 0
* The cache now contains 0 members
curl: (35) Unknown SSL protocol error in connection to localhost:3001
But these commands are returning successful connections when run on the Vagrant vm terminal!
What do I need to do to get my Windows PC/browser to accept the app's certificates so that I can access the app from Mozilla Firefox? Since it already has server.key and certs, surely I do not need to generate my own keys again for the app to use?
EDIT:
Here is my Vagrant file:
Vagrant.configure(2) do |config|
config.vm.box = "centos7"
config.vm.network "forwarded_port", guest: 3000, host: 3000, auto_correct: true
config.vm.network "forwarded_port", guest: 3001, host: 3001, auto_correct: true
end
I've only got the port forwarding configs..the rest are default.
And when the app is running on Vagrant, netstat shows that the port is listening for connection
$ netstat -an | grep 3001
TCP 0.0.0.0:3001 0.0.0.0:0 LISTENING
And when I access https://localhost:3001 on the browser, I see this:
netstat -an | grep 3001
TCP 0.0.0.0:3001 0.0.0.0:0 LISTENING
TCP 127.0.0.1:3001 127.0.0.1:49651 ESTABLISHED
TCP 127.0.0.1:49651 127.0.0.1:3001 ESTABLISHED
Seems like the port connections are fine, but vm is not able to return data.

After much digging around I stumbled upon this comment:
https://unix.stackexchange.com/a/255404
Because I was on CentOS 7, disabling firewalld did the trick for me. I didn't realize the change. In a sense, the note from joelnb to check iptables in his answer comments is the right direction (thanks!). Do check your OS's firewall and try disabling it to see if it helps with the issue. If yes, then you can proceed to configure a rule for the port if you wish.
For CentOS 7, to open a port on firewalld:
centos 7 - open firewall port
I hope this helps somebody.

I suspect that you don't have the port forward setup in your Vagrantfile because I get that exact error if I don't/if nothing is listening on that port. Does your Vagrantfile look like the following? The forwarded_port part is the important bit.
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.network "forwarded_port", guest: 3001, host: 3001
end
Otherwise could you please post your Vagrantfile and I will revise my answer.

Related

API GET Request test using Playwright

I have been trying to verify the GET status using the following code. Unfortunately, I am getting an error "apiRequestContext.get: connect ECONNREFUSED ::1:8080". Any insight would be much appreciated.
Code:
import { expect, test } from '#playwright/test';
test('Get health status', async ({ request }) => {
const response = await request.get('http://localhost:8080/myapp/actuator/health')
expect(response.status()).toBe(200)
})
Error:
apiRequestContext.get: connect ECONNREFUSED ::1:8080
Since NodeJS 17, node will prefer IPv6 over IPv4.
Verification
It might be that the service only listens on IPv4, but the client uses IPv6. Check for the words IPv4 or IPv6 in:
netstat -tulpen (on linux) or
sudo lsof -iTCP -sTCP:LISTEN -n -P 8080 | grep -i --color 8080 (on macOS).
Solutions
There are two options:
Enable IPv6 binding for the service. This depends on your service framework - search how to enable ipv6 for service XYZ in Google.
Configure NodeJS to prefer IPv4 over IPV6. Add to playwright.config.js:
import dns from "dns";
dns.setDefaultResultOrder("ipv4first");
If the service can handle, force the use of IPv4: connect to http://127.0.0.1:8080 instead of http://localhost:8080
Disable the IPv6 address for localhost for the whole machine.
Edit the hosts file (sudo vi /etc/hosts) and remove ::1 localhost.
Resources
See https://blog.apify.com/ipv4-mapped-ipv6-in-nodejs/
https://nodejs.org/api/dns.html#dnssetdefaultresultorderorder

WebSocket / wss not connecting, used Django Channels and AWS Elastic Beanstalk

Getting this webSocket error at site https://yoga.sightica.com/class/ console. Backend Django and deployed in AWS using elastic beanstalk.
Firefox can’t establish a connection to the server at wss://yoga.sightica.com/class/.
main.js:76:16
or in google chrome
main.js:76 WebSocket connection to 'wss://yoga.sightica.com/class/' failed:
(anonymous) # main.js:76
and this is my main.js file line 76
webSocket = new WebSocket(endPoint);
I have configured Django channels and Redis elastic cache using their official docs.
option_settings:
aws:elbv2:listener:80:
DefaultProcess: http
ListenerEnabled: 'true'
Protocol: HTTP
Rules: ws
aws:elbv2:listener:443:
ListenerEnabled: 'true'
Protocol: HTTPS
SSLCertificateArns: <substituted my ARN FROM AWS CERTIFICATES MANAGER>
SSLPolicy: ELBSecurityPolicy-2016-08
Rules: ws
aws:elbv2:listenerrule:ws:
PathPatterns: /ws/*
Process: websocket
Priority: 1
aws:elasticbeanstalk:environment:process:http:
Port: '80'
Protocol: HTTP
aws:elasticbeanstalk:environment:process:websocket:
Port: '5000'
Protocol: HTTP
This is my elastic beanstalk configuration. I need a proper .config file, other config tutorial are not deploying in elastic beanstalk for me.
i have used this Procfile (substituted my path)
web: gunicorn --bind :8000 --workers 3 --threads 2 <your_app>.wsgi:application
websocket: daphne -b 0.0.0.0 -p 5000 <your_app>.asgi:application
I need to get websocket in a HTTPS page, since i need to access webcam.
And the websocket is working in localhost.
( WebSocket() function can be seen here https://developer.mozilla.org/en-US/docs/Web/API/WebSocket )

Node.js localhost:3000 refuses to connect

I am a total beginner of Node.js and I am unable to connect to localhost:3000
I use the following code in VS code, hit "node app.js" in terminal, and there is no error comes out in terminal at this point.
However, as I try to access the localhost:3000, it keeps refusing: "ERR_CONNECTION_REFUSED"
I searched on the internet for solutions and tried opening ports by creating an inbound rule on security settings, turned IIS on, used 127.0.0.1 instead, and still get refused. Does anyone have any idea how to solve this?
I am using Windows 10
const http = require('http');
var server = http.createServer(
(request, response)=>{
response.end('hello');
}
);
server.listen(3000);
Here is how to fix it. Your probably try to launch your server on a used port.
// enter this command in your terminal
lsof -i:3000
// this will output the related PID (process ID). Here: 1382.
node 1382 name 21u IPv6 blabla 0t0 TCP *:3000 (LISTEN)
// kill the PID in use
kill -9 1382
//relaunch your server
node app.js
I ran it on my computer and that code works fine. I would try other ports to see if they work.

Hosting multiple Node.JS applications recognizing subdomains with a proxy server

I am trying to redirect certain subdomains to a specific port on my ubuntu AWS EC2 virtual server. Already tried it with DNS and that wouldn't work so based on the following topics, Default route using node-http-proxy? and How do I use node.js http-proxy for logging HTTP traffic in a computer?, I was trying to create a Node.JS proxy server with logging. That said I mixed it a bit up together (I'm new to Node.JS, still learning) and made the following script:
var httpProxy = require('http-proxy');
var PORT = 80;
logger = function() {
return function (request, response, next) {
// This will run on each request.
console.log(JSON.stringify(request.headers, true, 2));
next();
}
}
var options = {
// this list is processed from top to bottom, so '.*' will go to
// 'http://localhost:3000' if the Host header hasn't previously matched
router : {
'dev.domain.com': 'http://localhost:8080',
'beta.domain.com': 'http://localhost:8080',
'status.domain.com': 'http://localhost:9000',
'health.domain.com': 'http://localhost:9000',
'log.domain.com': 'http://localhost:9615',
'^.*\.domain\.com': 'http://localhost:8080',
'.*': 'http://localhost:3000'
}
};
// Listen to port 80
httpProxy.createServer(logger(), options).listen(PORT);
console.log("Proxy server started, listening to port" + PORT);
Well what happens is that I keep getting the following error and can't figure out how to put this to work:
$node proxyServer.js
Proxy server started, listening to port80
events.js:72
throw er; // Unhandled 'error' event
^
Error: listen EACCES
at errnoException (net.js:904:11)
at Server._listen2 (net.js:1023:19)
at listen (net.js:1064:10)
at Server.listen (net.js:1138:5)
at ProxyServer.listen (/home/ubuntu/QuantBull-Project/node_modules/http-proxy/lib/http-proxy/index.js:130:16)
at Object.<anonymous> (/home/ubuntu/QuantBull-Project/proxyServer.js:28:43)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
In short I'm trying to receive http request on port 80 and if it came from sub1.domain.com it will be redirected to portA and if it came frome sub2.domain.com it'll be redirected to portB from the same IP adress and both ports are open to the public.
Can someone explain how to fix this and explain why it happens?
Port Access:
As mentioned by the previous answer and comments the port below 1024 can't be opened by a regular user. This can be overcome by following these instruction:
If cat /proc/sys/net/ipv4/ip_forward returns 0 uncomment net.ipv4.ip_forward at the file /etc/sysctl.conf and enable these changes: sudo sysctl -p /etc/sysctl.conf, if it returns 1, skip this step;
Set up forwarding from port 80 to one desired above 1024 (i.e. port 8080): sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080;
Open up the Linux firewall to allow connections on port 80: sudo iptables -A INPUT -p tcp -m tcp --sport 80 -j ACCEPT and sudo iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
Note: To make these changes stick even when restarting the server you may check the this out.
http-proxy's routefeature is removed:
After taking care of the port access the proxy server continued without working, so after opening an issue it seemed that the routing feature was removed because, according to Nodejitsu Inc.:
The feature was removed due to simplicity. It belongs in a separate module and not in http-proxy itself as http-proxy is just responsible for the proxying bit.
So they recommended to use http-master.
Using http-master:
As described in http-master's README section, node.js is required and we need to run npm install -g http-master (may be needed to run as root depending on your setup). Then we create the config file, i.e. http-master.conf, were we add our routing details and for this specific question, the config file is as followed:
{
# To detect changes made to the config file:
watchConfig: true,
# Enable logging to stdout:
logging: true,
# Here is where the magic happens, definition of our proxies:
ports: {
# because we defined that Port 80 would be redirected to port 8080 before,
# we listen here to that port, could be added more, i.e. for the case of a
# secure connections trough port 443:
8080 : {
proxy: {
# Proxy all traffic for monitor subdomains to port 9000
'status.domain.com' : 9000,
'health.domain.com' : 9000,
# Proxy all traffic for logger subdomains to port 9615
'log.domain.com' : 9615,
# Proxy all traffic from remaining subdomains to port 8000
'*.domain.com' : 8000
},
redirect: {
# redirect .net and .org requests to .com
'domain.net': 'http://domain.com/[path]',
'domain.org': 'http://domain.com/[path]'
}
}
}
}
And we are almost done, now we just run it with: http-master --config http-master.conf and our subdomain routing should be working just fine.
Note: If you want to run the proxy server on the background I recommend using a tool like forever or pm2, and in the case of using pm2 I recommend reading this issue.
If you are running your proxy as a regular user (not root), you can't open ports below 1024. There may be a way to do this as a normal user but usually I just run such things as root.

Node JS "Hello world" server on AWS

I tried to run "Hello world" server on AWS t1.micro instance. What I done:
I installed Node on aws
Wrote something like this:
require("http").createServer(function(request, response){
response.writeHeader(200, {"Content-Type": "text/plain"});
response.write("Hello World!");
response.end();
}).listen(8080);
- Run it on aws: node test_server.js
Now I try to send request from my local machine to server like this:
curl http://NAME:8080 where NAME is public DNS name from aws console, but nothing happens.
What I forget? Or what I done wrong
I tried to look for a some kind of tutorial but they describe how to run this on local machine or propose to setup Ngnx. But I look for minimalist example
You need to tell Amazon to authorize inbound traffic on the 8080 port to your instance. See the documentation for the step by step instructions.
In short:
Go to the Amazon EC2 console, click on Instance and open the Security Group preference pane
Add a new rule authorizing inbound traffic from any IP (0.0.0.0/0) on port 8080
Apply changes: the Node web server should now be able to serve HTTP requests.
#Paul is right, but that was only a part of the solution for me. I was still getting "connection refused" from local machine (remote CURL was fine). So, another part was of the puzzle was solved by turning off the Unix firewall (in addition at AWS security groups configs), i.e., iptables!
Are you runing CentOS? Try this:
$ service iptables save
$ service iptables stop
$ chkconfig iptables off
Of course, turning off firewall and opening up AWS console security groups is not a good long-term idea. The proper way is to use iptable, open port 80 for inbound and outbound, and then reroute 80 to Node.js port (3000 or 1337 or something else):
$ sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
$ sudo iptables -A INPUT -p tcp -m tcp --sport 80 -j ACCEPT
$ sudo iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
You can also use Nginx to do the redirect . Varnish Cache is a good tool to have as well, because it dramatically decreases load on Node.js processes if you have a lot of users hitting one resource/page.
Further reading about AWS and Node.js:
http://www.lauradhamilton.com/how-to-set-up-a-nodejs-web-server-on-amazon-ec2
How to disable iptables on Linux:
http://www.cyberciti.biz/faq/turn-on-turn-off-firewall-in-linux/
Same on CentOS and Fedora:
http://www.cyberciti.biz/faq/disable-linux-firewall-under-centos-rhel-fedora/

Categories