We are unable get the public IP address of a client machine. It is showing the sdp is undefined while executing the code. Below is the code.
Get current IP in JS (no third party services)
https://github.com/diafygi/webrtc-ips
//get the IP addresses associated with an account
function getIPs(callback){
var ip_dups = {};
//compatibility for firefox and chrome
var RTCPeerConnection = window.RTCPeerConnection
|| window.mozRTCPeerConnection
|| window.webkitRTCPeerConnection;
var useWebKit = !!window.webkitRTCPeerConnection;
//bypass naive webrtc blocking using an iframe
if(!RTCPeerConnection){
//NOTE: you need to have an iframe in the page right above the script tag
//
//<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
//<script>...getIPs called in here...
//
var win = iframe.contentWindow;
RTCPeerConnection = win.RTCPeerConnection
|| win.mozRTCPeerConnection
|| win.webkitRTCPeerConnection;
useWebKit = !!win.webkitRTCPeerConnection;
}
//minimal requirements for data connection
var mediaConstraints = {
optional: [{RtpDataChannels: true}]
};
var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
//construct a new RTCPeerConnection
var pc = new RTCPeerConnection(servers, mediaConstraints);
function handleCandidate(candidate){
//match just the IP address
var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
var ip_addr = ip_regex.exec(candidate)[1];
//remove duplicates
if(ip_dups[ip_addr] === undefined)
callback(ip_addr);
ip_dups[ip_addr] = true;
}
//listen for candidate events
pc.onicecandidate = function(ice){
//skip non-candidate events
if(ice.candidate)
handleCandidate(ice.candidate.candidate);
};
//create a bogus data channel
pc.createDataChannel("");
//create an offer sdp
pc.createOffer(function(result){
//trigger the stun server request
pc.setLocalDescription(result, function(){}, function(){});
}, function(){});
//wait for a while to let everything done
setTimeout(function(){
//read candidate info from local description
var lines = pc.localDescription.sdp.split('\n');
lines.forEach(function(line){
if(line.indexOf('a=candidate:') === 0)
handleCandidate(line);
});
}, 1000);
}
//Test: Print the IP addresses into the console
getIPs(function(ip){console.log(ip);});
While executing the code we are getting this error message:
'Cannot read property 'sdp' of null'
The example code you are referencing is outdated and their demo page is no longer working either on recent Chrome versions:
https://diafygi.github.io/webrtc-ips/
Furthermore, it seems to use features that are not supported by some browsers.
I don't know your requirements but it is quite standard to send a request to a server in order to discover the public IP of a client. The server looks at headers (e.g. x-forwarded-for, this depends on the Web server used) and sends it back to the requester.
There also exist services such as Ipregistry (disclaimer: I run the service) that do it for you and return even more interesting information: client IP address, location, currency, threat data, etc.
As of this writing, you cannot leak the private IP address of your users.
However, I found a github repo webrtc-ip which can leak a user's public IP address using WebRTC. This is powerful because you cannot trace it, as nothing is shown in the Networks tab.
Sadly, this leak does not work for private IPs, due to the gradual shift to mDNS (at least for WebRTC), which is completely in this great blog. Regardless, here's a working demo:
https://webrtc-ip.herokuapp.com/
I am not sure if this leaks your true IP address regardless of a proxy, but feel free to test it out.
If you look at the repo you referenced, the issues clearly state that the repo does not work and that the repository is not being maintained.
Related
Firefox and Chrome have implemented WebRTC that allow requests to STUN servers be made that will return the local IP address of the client.
The javascript code below outputs the local IP address of the client:
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};
pc.createDataChannel(""); //create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop); // create offer and set local description
pc.onicecandidate = function(ice){ //listen for candidate events
if(!ice || !ice.candidate || !ice.candidate.candidate) return;
var myIP = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
console.log('my IP: ', myIP);
pc.onicecandidate = noop;
};
Is it possible to obtain the MAC address also?
No you cannot get the MacAdress with Javascript in the Browser. For very good reasons. It would be a big security risk.
The MAC address uniquely identifies the running computer, cellphone...basically every device, an internal IP does not.
You need to use Electron or Node for that, if you want to do it with Javascript.
Use ARP using any way. You can use OS API or you can spawn command line tool or high level API or library of you favorite programming language.
My scenario is to get MAC and IP address of connected PCs not over the Internet But locally in LAN, and I also wanted to store that data into a database.
I searched google and found that we can get these values using Javascript. But I am new to this can someone please elaborate the proper solution?
It is probably the duplicate of this.
You can get the IP Address of the client machine by trying following code:
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};
pc.createDataChannel(""); //create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop); // create offer and set local description
pc.onicecandidate = function(ice){ //listen for candidate events
if(!ice || !ice.candidate || !ice.candidate.candidate) return;
var myIP = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
console.log('my IP: ', myIP);
pc.onicecandidate = noop;
};
Although for MAC Address I am not so sure that you can do it using javascript in a web application becuase the MAC address uniquely identifies the client computer so it can be a security issue.
Now if you want some unique identifier to use in your application that uniquely identifies the client's computer you can do some cryptography and use client cookies to store the values.
Although MAC Address can be accessed only in IE and only if user allows the plugin to run through following
function networkInfo(){
var wmi = new ActiveXObject ("WbemScripting.SWbemLocator");
var service = wmi.ConnectServer(".");
e = new Enumerator(service.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True"));
for(; !e.atEnd(); e.moveNext()) {
var s = e.item();
var macAddress = unescape(s.MACAddress);
}
return macAddress;
}
Sources:
- MAC addresses in JavaScript
- How to get client MAC address by using javascript?
- Can You Get A Users Local LAN IP Address Via JavaScript?
I'm creating a web application and in order for it to run, you must have your device 'registered'. The registration process involves entering the IPv4 address of the device you wish to use into a field which updates the database.When accessing the application, it goes through a window.webkitRTCPeerConnection or window.mozRTCPeerConnection check to get the IP address. This works on the latest versions of Chrome and Firefox, but not IE. So, I had to use ActiveX if the IP wasn't obtained from the RTCPeerConnection check.My problem is that I want Safari to be able to run the application, but I can't seem to find anything on how to get the IPv4 address for devices running Safari.To clarify, this web application is not open for general public usage and we'll have complete control over what's installed on devices running the application. (That's my justification for using ActiveX).Any suggestions and/or references to how I can do such a thing would be appreciated.
Please try this way.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h4>
Demo for:
<a href="https://github.com/diafygi/webrtc-ips">
https://github.com/diafygi/webrtc-ips
</a>
</h4>
<p>
This demo secretly makes requests to STUN servers that can log your
request. These requests do not show up in developer consoles and
cannot be blocked by browser plugins (AdBlock, Ghostery, etc.).
</p>
<h4>Your local IP addresses:</h4>
<ul></ul>
<h4>Your public IP addresses:</h4>
<ul></ul>
<h4>Your IPv6 addresses:</h4>
<ul></ul>
<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
<script>
//get the IP addresses associated with an account
function getIPs(callback){
var ip_dups = {};
//compatibility for firefox and chrome
var RTCPeerConnection = window.RTCPeerConnection
|| window.mozRTCPeerConnection
|| window.webkitRTCPeerConnection;
var useWebKit = !!window.webkitRTCPeerConnection;
//bypass naive webrtc blocking using an iframe
if(!RTCPeerConnection){
//NOTE: you need to have an iframe in the page right above the script tag
//
//<iframe id="iframe" sandbox="allow-same-origin" style="display: none"></iframe>
//<script>...getIPs called in here...
//
var win = iframe.contentWindow;
RTCPeerConnection = win.RTCPeerConnection
|| win.mozRTCPeerConnection
|| win.webkitRTCPeerConnection;
useWebKit = !!win.webkitRTCPeerConnection;
}
//minimal requirements for data connection
var mediaConstraints = {
optional: [{RtpDataChannels: true}]
};
var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
//construct a new RTCPeerConnection
var pc = new RTCPeerConnection(servers, mediaConstraints);
function handleCandidate(candidate){
//match just the IP address
var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
var ip_addr = ip_regex.exec(candidate)[1];
//remove duplicates
if(ip_dups[ip_addr] === undefined)
callback(ip_addr);
ip_dups[ip_addr] = true;
}
//listen for candidate events
pc.onicecandidate = function(ice){
//skip non-candidate events
if(ice.candidate)
handleCandidate(ice.candidate.candidate);
};
//create a bogus data channel
pc.createDataChannel("");
//create an offer sdp
pc.createOffer(function(result){
//trigger the stun server request
pc.setLocalDescription(result, function(){}, function(){});
}, function(){});
//wait for a while to let everything done
setTimeout(function(){
//read candidate info from local description
var lines = pc.localDescription.sdp.split('\n');
lines.forEach(function(line){
if(line.indexOf('a=candidate:') === 0)
handleCandidate(line);
});
}, 1000);
}
//insert IP addresses into the page
getIPs(function(ip){
var li = document.createElement("li");
li.textContent = ip;
//local IPs
if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/))
document.getElementsByTagName("ul")[0].appendChild(li);
//IPv6 addresses
else if (ip.match(/^[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}$/))
document.getElementsByTagName("ul")[2].appendChild(li);
//assume the rest are public IPs
else
document.getElementsByTagName("ul")[1].appendChild(li);
});
</script>
</body>
</html>
This API can get your IP adress.
https://l2.io/
More advanced solution:
http://dev.maxmind.com/geoip/geoip2/javascript/
This one also supports Safari, according to this: http://dev.maxmind.com/geoip/geoip2/javascript/#Browser_Support
The last one is in my opinion the best one. I use that one in one of my projects.
EDIT:
On safari there is no support yet for WebRTC Connections. So it is not possible to obtain the local IP adress on safari.
The website https://api.ipify.org knows your ip adress. The only thing you have to do is scrape it. You can do that with JavaScript.
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "https://api.ipify.org", false);
xhttp.send();
var ip = xhttp.responseText;
I am creating an application acquiring the client's IP address frequently (about per second) in JavaScript.
Because of a possible BAN, I do not want to use services providing the client's IP address such as l2.io if I can.
Also, I do not want to prepare the API providing the client's IP address on my web server if I can.
I found WebRTC helpful to solve the problem and tried writing the function acquiring the client's IP address using WebRTC.
It seems that the function works well but I found the function causing a memory leak.
The following is my code causing a memory leak in Chrome 47.
function getIpAddress() {
return new Promise((resolve, reject) => {
var RTCPeerConnection = window.RTCPeerConnection
|| window.mozRTCPeerConnection
|| window.webkitRTCPeerConnection;
var pc = new RTCPeerConnection({
iceServers: [{urls: "stun:stun.services.mozilla.com"}]
}, {
optional: [{RtpDataChannels: true}]
});
pc.onicecandidate = ice => {
if (pc.iceGatheringState == "complete" && ice.candidate === null) { // waiting for completion
resolve(pc.localDescription.sdp.split("\r\n").filter(line => line.indexOf("c=") == 0)[0].split(" ")[2]);
if (pc.signalingState != "closed") pc.close();
}
};
pc.createDataChannel("");
pc.createOffer(result => {
pc.setLocalDescription(result, function () {}, function () {});
}, function () {});
});
}
// calling getIpAddress many times causes a memory leak
(function loop() {
getIpAddress().then(loop);
})();
Do you know which part of getIpAddress causes a memory leak?
If you do not know, is there another way to acquire the client's IP address without a memory leak?
Note:
I have already tried webrtc-ips but it seems that webrtc-ips also causes a memory leak.
I'm not sure that looping the WebRTC request is planned "by design".
Do you have a memory leak when doing the function only once ?
Normally, you need to catch the IP only once by client.
In my firefox, no memory leak, only a big processor charge because of the loop.
If you can use PHP, acquiring IP address would be very easy.
Do you know which part of getIpAddress causes a memory leak?
It seems that instantiating RTCPeerConnection many times causes a memory leak.
The following code causes a memory leak and may crash Chrome 47 and Firefox 43.
while (true) {
var RTCPeerConnection = window.RTCPeerConnection
|| window.mozRTCPeerConnection
|| window.webkitRTCPeerConnection;
var pc = new RTCPeerConnection({});
pc.close();
}
How can I get the local client IP using WebRTC.
I don't need the REMOTE_ADDR of the client but his local network IP.
I've seen this before on websites like sharedrop.com, it recognizes computer within the same network using WebRTC.
In PHP I do this to get the clients remote IP:
<?php
echo $_SERVER["REMOTE_ADDR"]; // which would return 72.72.72.175
?>
I looked through stackoverflow but every question is answered using the remote addr.
How can I get my local IP (192.168.1.24 for example) with JavaScript instead of the remote addr.
UPDATE
Unfortunately the below answer no longer works as browsers have changed this behavior due to security concerns. See this StackOverflow Q&A for more details.
where I took code from --> Source
You can find a demo at --> Demo
I have modified the source code, reduced the lines, not making any stun requests since you only want Local IP not the Public IP, the below code works in latest Firefox and Chrome:
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chrome
var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};
pc.createDataChannel(""); //create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop); // create offer and set local description
pc.onicecandidate = function(ice){ //listen for candidate events
if(!ice || !ice.candidate || !ice.candidate.candidate) return;
var myIP = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
console.log('my IP: ', myIP);
pc.onicecandidate = noop;
};
what is happening here is, we are creating a dummy peer connection, and for the remote peer to contact us, we generally exchange ice candidates with each other. And reading the ice candiates we can tell the ip of the user.
You can use this version on modern browser (with Promises and async / await)
// minified onliner, 219b
const ip = await new Promise((s,f,c=new RTCPeerConnection(),k='candidate')=>(c.createDataChannel(''),c.createOffer(o=>c.setLocalDescription(o),f),c.onicecandidate=i=>i&&i[k]&&i[k][k]&&c.close(s(i[k][k].split(' ')[4]))))
Or, un-minified:
// cleaned, 363b
const ip = await new Promise((resolve, reject) => {
const conn = new RTCPeerConnection()
conn.createDataChannel('')
conn.createOffer(offer => conn.setLocalDescription(offer), reject)
conn.onicecandidate = ice => {
if (ice && ice.candidate && ice.candidate.candidate) {
resolve(ice.candidate.candidate.split(' ')[4])
conn.close()
}
}
})