NodeJS DNS Reverse Lookup - node.js

I need to get the host name of the client from its IP. I tried to use Node's DNS Reverse module and it works for external IP's but not internal IP's.
const dns = require('dns');
var ip = req.headers['x-forwarded-for'];
dns.reverse(ip, function(err, hostnames) {
if (err) console.log(`Couldn't reverse IP ${ip}:`, err);
else console.log(`IP ${ip} maps to:`, hostnames);
});
I get error ENOTFOUND for my internal IP. But if I use 8.8.8.8, I will get a host name. Am I missing something with my configuration? I have tested on this on the server using CMD to get the host name by ping -a [internal IP] and it works.

Related

502 error and unhealthy health status in the target group when using AWS ELB and ACM for https

I'm using AWS ELB and ACM to use HTTPS on Node.js but, I have been facing 502 error.
The health status of the target group for the HTTPS is "unhealthy" which is making me understand I'm doing something wrong around ELB.
The following is what I did.
[ELB]
VPC: Same VPC with the EC2 instance
Subnet #1: 10.0.1.0/24: Same subnet with the EC2 instance
Subnet #2: 10.0.3.0/24: New subnet which was created for this test
Security group: All traffic for inbound & outbound are opened (for this test purpose)
Listener_a(http:80):
Rule1:
(If) Host is [example].com OR www.[example].com
(Then) Redirect to https://www.[example].com:443/#{path}?#{query}
(path and query are untouched from the default placeholder)
Status code: HTTP_301
Rule last: untouched from the default
Listener_b(https:443):
Rule1:
(If) Host is [example].com
(Then) Redirect to https://www.[example].com:443/#{path}?#{query}
(path and query are untouched from the default placeholder)
Status code: HTTP_301
Rule last: untouched from the default
[Target groups of ELB]
Target group #1:
[Target type] [Protocol version] [Instance ID] [Name] [Port] [Zone] [Health status]
Instance HTTP1 [Instance ID of the EC2] testname1 80 us-east-2b healthy
Target group #2:
[Target type] [Protocol version] [Instance ID] [Name] [Port] [Zone] [Health status] [Health status details]
Instance HTTP1 [Instance ID of the EC2] testname2 443 us-east-2b unealthy "Health checks failed"
[Summary of ELB log]
type: h2
target:port: Private IPv4 address of the EC2 instance
request_processing_time: -1
target_processing_time: -1
response_processing_time: -1
elb_status_code: 502
target_status_code: -
request: GET https://www.[example].com:443/HTTP/2.0
[Route 53]
[Record name] [Type] [Routing Policy] [Differentiator] [Value/Route traffic to]
[example].com A Simple - www.[example].com.
www.[example].com A Simple - dualstack.[DNS name of the ELB].
[CNAME name of *.[example].com from ACM] CNAME Simple - [CNAME value from ACM]
[CNAME name of www.[example].com from ACM] CNAME Simple - [CNAME value from ACM]
[example].com NS Simple - [4 Name Servers added by Route 53]
[example].com SOA Simple - [Value added by Route 53]
[ACM]
[Domain] [Status]
*.[example].com Success
[example].com Success
www.[example].com Success
[EC2]
VPC: Same VPC with the ELB (10.0.0.0/16)
Subnet #1: Same subnet with the one of the subnet assinged to ELB (10.0.1.0/24)
Public IPv4 address: [ElasticIP assigned]
Security group: All traffic for inbound & outbound are opened (for this test purpose)
[Routing table (same for both subnet)]
[Destination] [Target]
10.0.0.0/16 local
0.0.0.0/0 [IGW]
[ACLs]
All are allowed for both Inbound and Outbound(for this test purpose).
[iptables I ran on EC2]
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000
# iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8443
[Node.js code on EC2 (index.js)]
const fs = require('fs');
const http = require('http');
const https = require('https');
const express = require('express');
const app = express();
const path = require('path');
app.get('/', (req, res) => {
res.send("Hello World!");
});
const httpServer = http.createServer(app);
const httpsServer = https.createServer(app);
httpServer.listen(8000, () => {
console.log("App is listening on port 8000");
});
httpsServer.listen(8443, () => {
console.log("App is listening on port 8443");
});
[Summary of results accessing from browser]
https://www.[example.com] => "502 Bad Gateway"
http://[example].com => Browser redirect it to https://www.[example].com and returns "502 Bad Gateway"
[my Elastic IP] => Can see the web page w/o error
[Public IPv4 DNS of the EC2 instance] => Can see the web page w/o error
[DNS name] => Can see the web page w/o error
[Summary of results accessing from EC2 command line with curl]
http://www.[example].com => 301 Moved Permanently
https://www.[example].com => 502 Bad Gateway
I tried to figure out what is wrong based on the following documents but, so far, no luck.
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#enable-access-logging
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html
https://aws.amazon.com/premiumsupport/knowledge-center/elb-fix-failing-health-checks-alb/
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html
https://aws.amazon.com/premiumsupport/knowledge-center/troubleshoot-unhealthy-checks-ecs/
If anyone could provide me with your insight about what I am missing/doing wrong, it would be great. Please let me know if there is any other information needed.
Thank you!
[Additional edits (8/21/2022)]
As it looked similar to what was discussed on this thread (https://stackoverflow.com/questions/60738575/target-group-443-gives-health-checks-failed-with-these-codes-502?rq=1), I just tried changing the Health check protocol for the target group of HTTPS to use HTTP; however, the results (unhealthy) were the same.
Thanks to the comment from Mark, I updated it as follows and everything is working perfectly, now.
[Target groups of ELB]
Delete the target group for HTTPS and just keep the one for HTTP only.
[ELB]
Update the listener for HTTPS to forward to the target group for HTTP (it was originally forwarding to the target group for HTTPS)
After the update, both listeners for HTTP and HTTPS are forwarded to the same target group for HTTP. It seems like this part was the key.
[Node.js code]
Removed the listeners for https (443) as it was not needed and just keep the one for http (80) only.
[iptables]
Stop running iptables for 8443 as it was not needed and just keep the one for 8000 only.
This thread about running Node.js with port 80 was also helpful. ([https://stackoverflow.com/questions/16573668/best-practices-when-running-node-js-with-port-80-ubuntu-linode][1]).

nodejs request module returning ECONNREFUSED on localhost

I am trying to make an api call to my localhost but I always get
Error: connect ECONNREFUSED 127.0.0.1:5005 at Object.exports._errnoException (util.js:1022:11)
var url = `http://127.0.0.1:5005/api/entities/myEndpoint?id=121`;
var options = {
url: url
};
request.get(options, function(err, response, body) {
console.log(err, response,body);
});
It does work if I use an IP instead of localhost
Check if your server has bound the port to its external IP only. On Linux, check netstat -tulpen | grep 5005. The output will contain the Server's listener address, e.g. 0.0.0.0:5005 or ::5005 both means that the server listens on all Interfaces for port 5005.
If your result is something like <ip address>:5005 where ip address is different from 127.0.0.1 that means that the server listens on that ip and port combination only and cannot be accessed using localhost, even if you are logged into the server.

Port forwarding not working for Nodejs application

I am running my Nodejs application on port 9000. I want the application to be accessible from a public IP address.
I went to my router config and did:
My Nodejs application is still running on localhost:9000 but when I go to
mypublicipaddress:9000
I get this site cannot be reached.
I also tried the netsh command:
netsh interface portproxy add v4tov4 listenport=9000 connectport=9000 connectaddress=192.168.1.12
This did not throw any error message but this also did not work.
I went to my router config and did: [...]
My Nodejs application is still running on localhost:9000
This implies that you've bound your Node.js server to your loopback interface on your machine and are trying to reach it from your router which is impossible. Try to bind the server to an IP address that is reachable by the router or bind it to all IP addresses on your local machine (ie. 0.0.0.0 or ::).
For example:
const http = require('http');
const server = http.createServer((req, res) => { res.end('It works') });
server.listen(9000, '0.0.0.0');
As for the netsh command, I think you should also set the listenaddress to your machine address on your network (or 0.0.0.0). Also, connectaddress must be set to 127.0.0.1:
netsh interface portproxy add v4tov4 listenport=9000 connectport=9000 connectaddress=127.0.0.1 listenaddress=192.168.1.12

DNS lookup from dokku container

I'm running a node app inside a dokku container on an Ubuntu server, which also runs bind9 for DNS. In the node app, I'm running express. On the node app, I'm running a DNS reverse lookup on the client's IP like this (simplified):
const dns = require('dns');
const app = require('express')();
app.get('/myhostname', (req, res) => {
dns.reverse(req.headers['x-forwarded-for'], (err, hostnames) => {
res.json({ hostname: hostnames[0] });
});
});
This works fine locally, but once deployed to the dokku container, fails with an ENOTFOUND error. Presumably this is because the app isn't set to use the Ubuntu server as its DNS server. So I tried this right after require('dns'):
dns.setServers([process.env.DNS_SERVERS])
where DNS_SERVERS is set to either the local LAN ip of the server, or its docker internal IP. Either of those addresses results in a delay and eventual timeout trying to get the address.
How should I go about this?
The solution was this:
Set DNS_SERVERS=172.17.0.1
Allow requests through the firewall on the docker0 interface
Make sure bind is listening on 172.17.0.1 and that it is set to allow requests from the 172.17.0.0/16 range
The second item on the list is what I wasn't considering...

Publish Node.JS server on the internet

I have a Node.JS server that works fine on localhost. Now I want it accessible from the internet, hosted by my machine. My public IP address (the one that Google tells me I have) does not seem to be "accessible":
https.createServer({
key: privateKey,
cert: certificate
}, server).listen(80, '86.151.23.17');
fails with the following Node.JS error:
Error: listen EADDRNOTAVAIL
at errnoException (net.js:770:11)
at Server._listen2 (net.js:893:19)
at listen (net.js:937:10)
at Server.listen (net.js:994:9)
at dns.js:71:18
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
How can I publish my Node.JS server to my public IP address?
[Note: I do not have another webserver running. Also, I have tried various different ports as suggested here.]
You are most likely behind a router so your public IP is not available anywhere but on the router itself. What you need to do is listening on your private IP (usually somehing in the 192.168.* range) and setup a port forward on your router.
In case you are on Linux you'll also want to use a port >1024 instead of 80 so you don't have to run node as root. When setting up the port forwarding you can simply forward port 80 to whatever port your node server is running on.
const http = require("http");
const hostname = '0.0.0.0';
const port = 80;
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
using 0.0.0.0 will start listing to the public internet I have tested it.
I have experienced the cases that the ISP given router is intercepting default 80 and 443 ports. Even though the ports are opened. So better check server first using a port like 8080 etc.
And also configure port forwarding to a static local address (ipconfig /all assumed your host is windows) then assigned that IP address to your host using host's MAC address.
for a better experience, if you don't have a static IP, use noip.com dynamic domain names to access your server at any time (without knowing IP address).
Your app should listen on other ip address, example
app.listen(3000,'0.0.0.0');
or just
app.listen(3000);
Then you must open port forwarding in your modem. Like this http://www.dlink.com/uk/en/support/faq/routers/wireless-routers/dkt-series/how-do-i-open-up-ports-to-my-computer-port-forwarding-on-this-router
Finally you can see your app at ip address in here https://whatismyipaddress.com/

Resources