How to get mac address of client in node js? - node.js

Is it possible to get mac address from the incoming request object?
My application is gonna be used locally on the same subnet and it runs behind a nginx proxy.

You need a tool that accesses the ARP table (a table that contains MAC addresses of IPs in your local network). Something like this arp-lookup package. You can extract the incoming request ip. Then use this IP to extract the MAC address with the arp-lookup.
The code would be something like this:
const{ toMAC } = require('#network-utils/arp-lookup');
// ...
async function handleIncomingRequest( req, res ) {
const ip = req.connection.remoteAddress;
const mac = await toMAC(ip);
// do stomething with the MAC address...
}

Related

How to send traffic over a specific external network interface from node.js?

I have 2 network interfaces on a MacOS machine: "ZTE Mobile Broadband" and "Ethernet". Both can be used to access the Internet. Is it possible to influence how a specific URL will be requested from node.js? E.g. got('https://ifconfig.co', {/* something to mark traffic to make the OS send this specific request over eth or zte */})?
I know you can add routes to request specific destinations over specific interfaces, and that you can mark traffic from a certain process id and then make all traffic from this process go over specific interface, but what about single requests from a process?
#user2226755 for the bounty "Do you know a way to do a HTTP request in node over a specific interface ?"
the "specific" interface is specified in the form of the provided ip address.
you could get it with somthing like
import { networkInterfaces } from 'os';
const interfaces = networkInterfaces();
...
or
const interface_ip = require('os').networkInterfaces()['Ethernet']['address'] // Ethernet being NIC name.
then, like Franco Rondini said, use a custom agent, per this github issue thread.
const http = require('http')
const https = require('https')
const options = { localAddress: interface_ip, /* taken from networkInterfaces() */ /* family: 4 // optional for ipv4, but set to 6 if you use ipv6 */ }
const httpAgent = new http.Agent(options)
const httpsAgent = new https.Agent(options)
axios.get('https://example.com/', { httpAgent, httpsAgent })
// you don't have to use both http and https if you know which of these protocols the website is using
and without axios:
https://stackoverflow.com/a/20996813/4935162
now I can't test your exact scenario, but you could try setting the IP of the interface you'd like to use into the localAddress option as pointed in this answer
or providing a custom agent as exemplified in this workaround

How to get local IP address of user connected through request - Nodejs

I have not been able to find any answer to this. I am looking for a way to obtain the local IP address of the user connected to my node server. I found the answer to find a way to get the user's public IP address, and was useful. I also need a way to determine which computer is connected, so the local IP as well through, possibly, something like this:
app.post('getip', function(req,res)
{
var localIP = req.headers['something or other'];
}
Thanks,
This should get you the IP in NodeJS if you're behind a proxy like nginx.
app.post('getip', function(req, res)
{
var localIP = req.headers["x-forwarded-for"];
}

GeoIP in localhost

I am using GeoIP to get country from client address but it returns null
ip = (req.headers['x-forwarded-for'] || '').split(',')[0] || req.connection.remoteAddress;
country = geoip.lookup(ip).country;
I think this is because I am using localhost since the detected ip is 127.0.1.
How to solve that?
You can use services like http://fugal.net/ip.cgi or http://ifconfig.me/ip to get your external IP address via http.get() or run a shell command using child_process.exec() (like $ ip on OS X), but it's not a cross-platform solution. I don't think it's possible to get local machine external IP using http.IncomingMessage object (req) or os.networkInterfaces() method.
In your case, I would default to some country/latitude/whatever you need in case of null from geoip.lookup(), at least in development environment.
var geo = geoip.lookup(ip);
var country = geo ? geo.country : 'US';

How to get the correct IP address of a client into a Node socket.io app hosted on Heroku?

I recently hosted my first Node app using Express and socket.io on Heroku and need to find the client's IP address. So far I've tried socket.manager.handshaken[socket.id].address, socket.handshake.address and socket.connection.address , neither of which give the correct address.
App: http://nes-chat.herokuapp.com/ (also contains a link to GitHub repo)
To view IPs of connected users: http://nes-chat.herokuapp.com/users
Anyone know what the problem is?
The client IP address is passed in the X-Forwarded-For HTTP header. I haven't tested, but it looks like socket.io already takes this into account when determining the client IP.
You should also be able to just grab it yourself, here's a guide:
function getClientIp(req) {
var ipAddress;
// Amazon EC2 / Heroku workaround to get real client IP
var forwardedIpsStr = req.header('x-forwarded-for');
if (forwardedIpsStr) {
// 'x-forwarded-for' header may return multiple IP addresses in
// the format: "client IP, proxy 1 IP, proxy 2 IP" so take the
// the first one
var forwardedIps = forwardedIpsStr.split(',');
ipAddress = forwardedIps[0];
}
if (!ipAddress) {
// Ensure getting client IP address still works in
// development environment
ipAddress = req.connection.remoteAddress;
}
return ipAddress;
};
You can do it in one line.
function getClientIp(req) {
// The X-Forwarded-For request header helps you identify the IP address of a client when you use HTTP/HTTPS load balancer.
// http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/TerminologyandKeyConcepts.html#x-forwarded-for
// If the value were "client, proxy1, proxy2" you would receive the array ["client", "proxy1", "proxy2"]
// http://expressjs.com/4x/api.html#req.ips
var ip = req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'].split(',')[0] : req.connection.remoteAddress;
console.log('IP: ', ip);
}
I like to add this to middleware and attach the IP to the request as my own custom object.
The below worked for me.
Var client = require('socket.io').listen(8080).sockets;
client.on('connection',function(socket){
var clientIpAddress= socket.request.socket.remoteAddress;
});

Get remote IP adress not working on node

I'm trying to get the remote IP address from an incoming connection using express. Already tried the common solutions found in the web:
req.headers['x-forwarded-for'] / result: always undefined
req.socket.remoteAddress / result: always getting the Gateway IP (IE: 192.168.1.1) instead of the external address.
Any clues?
Are you testing this by running the app in a VM on your own machine? If so, you're getting the right answer. The X-Forwarded-For is empty, since there's no proxy, and you're seeing the virtual interface on the host machine which the VM uses to route out from. That's the IP from which the request comes.
Here's some code i used at http://th.issh.it/ip
Maybe it's case sensitive?
exports.iptoy = function(req,res) {
var clientip = req.socket.remoteAddress;
var xffip = req.header('X-Forwarded-For');
var ip = xffip ? xffip : clientip;
if(req.params.format == 'json')
res.send({client:clientip,xforwardedfor:xffip});
else
res.send(ip+"\n");
}

Resources