i literally cant remove these fucking files bullshit
parent
9c73ec3acf
commit
d06c108106
326
upnp.js
326
upnp.js
|
|
@ -1,163 +1,163 @@
|
||||||
/* node UPNP port forwarding PoC
|
/* node UPNP port forwarding PoC
|
||||||
This is a simple way to forward ports on NAT routers with UPNP.
|
This is a simple way to forward ports on NAT routers with UPNP.
|
||||||
This is a not-for-production hack that I found useful when testing apps
|
This is a not-for-production hack that I found useful when testing apps
|
||||||
on my home network behind ny NAT router.
|
on my home network behind ny NAT router.
|
||||||
-satori / edited by smolleyes for freebox v6
|
-satori / edited by smolleyes for freebox v6
|
||||||
usage: (install/clone node-ip from https://github.com/indutny/node-ip)
|
usage: (install/clone node-ip from https://github.com/indutny/node-ip)
|
||||||
================================================================================
|
================================================================================
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
*/
|
*/
|
||||||
var url = require("url");
|
var url = require("url");
|
||||||
var http = require("http");
|
var http = require("http");
|
||||||
var dgram = require("dgram");
|
var dgram = require("dgram");
|
||||||
var Buffer = require("buffer").Buffer;
|
var Buffer = require("buffer").Buffer;
|
||||||
|
|
||||||
// some const strings - dont change
|
// some const strings - dont change
|
||||||
const SSDP_PORT = 1901;
|
const SSDP_PORT = 1901;
|
||||||
const bcast = "239.255.255.250";
|
const bcast = "239.255.255.250";
|
||||||
const ST = "urn:schemas-upnp-org:device:InternetGatewayDevice:1";
|
const ST = "urn:schemas-upnp-org:device:InternetGatewayDevice:1";
|
||||||
const req = "M-SEARCH * HTTP/1.1\r\nHost:239.255.255.250:1900\r\n\
|
const req = "M-SEARCH * HTTP/1.1\r\nHost:239.255.255.250:1900\r\n\
|
||||||
ST:"+ST+"\r\nMan:\"ssdp:discover\"\r\nMX:3\r\n\r\n";
|
ST:"+ST+"\r\nMan:\"ssdp:discover\"\r\nMX:3\r\n\r\n";
|
||||||
const WANIP = "urn:schemas-upnp-org:service:WANIPConnection:1";
|
const WANIP = "urn:schemas-upnp-org:service:WANIPConnection:1";
|
||||||
const OK = "HTTP/1.1 200 OK";
|
const OK = "HTTP/1.1 200 OK";
|
||||||
const SOAP_ENV_PRE = "<?xml version=\"1.0\"?>\n<s:Envelope \
|
const SOAP_ENV_PRE = "<?xml version=\"1.0\"?>\n<s:Envelope \
|
||||||
xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" \
|
xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" \
|
||||||
s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>\n";
|
s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>\n";
|
||||||
const SOAP_ENV_POST = "</s:Body>\n</s:Envelope>\n";
|
const SOAP_ENV_POST = "</s:Body>\n</s:Envelope>\n";
|
||||||
|
|
||||||
function searchGateway(timeout, callback) {
|
function searchGateway(timeout, callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var reqbuf = new Buffer(req, "ascii");
|
var reqbuf = new Buffer(req, "ascii");
|
||||||
var socket = new dgram.Socket('udp4');
|
var socket = new dgram.Socket('udp4');
|
||||||
var clients = {};
|
var clients = {};
|
||||||
var t;
|
var t;
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
t = setTimeout(function() {
|
t = setTimeout(function() {
|
||||||
onerror(new Error("searchGateway() timed out"));
|
onerror(new Error("searchGateway() timed out"));
|
||||||
}, timeout);
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
var onlistening = function() {
|
var onlistening = function() {
|
||||||
|
|
||||||
socket.setBroadcast(socket.fd, true);
|
socket.setBroadcast(socket.fd, true);
|
||||||
// send a few packets just in case.
|
// send a few packets just in case.
|
||||||
socket.send(reqbuf, 0, reqbuf.length, SSDP_PORT,bcast);
|
socket.send(reqbuf, 0, reqbuf.length, SSDP_PORT,bcast);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var onmessage = function(message, rinfo) {
|
var onmessage = function(message, rinfo) {
|
||||||
|
|
||||||
console.log('message?')
|
console.log('message?')
|
||||||
message = message.toString();
|
message = message.toString();
|
||||||
|
|
||||||
if (message.substr(0, OK.length) !== OK ||
|
if (message.substr(0, OK.length) !== OK ||
|
||||||
!message.indexOf(ST) ||
|
!message.indexOf(ST) ||
|
||||||
!message.indexOf("location:")) return;
|
!message.indexOf("location:")) return;
|
||||||
|
|
||||||
var l = url.parse(message.match(/location:(.+?)\r\n/i)[1].trim());
|
var l = url.parse(message.match(/location:(.+?)\r\n/i)[1].trim());
|
||||||
if (clients[l.href]) return;
|
if (clients[l.href]) return;
|
||||||
|
|
||||||
var client = clients[l.href] = http.createClient(l.port, l.hostname);
|
var client = clients[l.href] = http.createClient(l.port, l.hostname);
|
||||||
var request = client.request("GET", l.pathname, {"host": l.hostname});
|
var request = client.request("GET", l.pathname, {"host": l.hostname});
|
||||||
request.end();
|
request.end();
|
||||||
request.addListener('response', function (response) {
|
request.addListener('response', function (response) {
|
||||||
if (response.statusCode !== 200) return;
|
if (response.statusCode !== 200) return;
|
||||||
var resbuf = "";
|
var resbuf = "";
|
||||||
response.addListener('data', function (chunk) { resbuf += chunk });
|
response.addListener('data', function (chunk) { resbuf += chunk });
|
||||||
response.addListener("end", function() {
|
response.addListener("end", function() {
|
||||||
resbuf = resbuf.substr(resbuf.indexOf(WANIP) + WANIP.length);
|
resbuf = resbuf.substr(resbuf.indexOf(WANIP) + WANIP.length);
|
||||||
var ipurl = resbuf.match(/<controlURL>(.+?)<\/controlURL>/i)[1].trim()
|
var ipurl = resbuf.match(/<controlURL>(.+?)<\/controlURL>/i)[1].trim()
|
||||||
socket.close();
|
socket.close();
|
||||||
clearTimeout(t);
|
clearTimeout(t);
|
||||||
callback(null, new Gateway(l.port, l.hostname, ipurl));
|
callback(null, new Gateway(l.port, l.hostname, ipurl));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var onerror = function(err) {
|
var onerror = function(err) {
|
||||||
socket.close() ;
|
socket.close() ;
|
||||||
clearTimeout(t);
|
clearTimeout(t);
|
||||||
callback(err);
|
callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var onclose = function() {
|
var onclose = function() {
|
||||||
socket.removeListener("listening", onlistening);
|
socket.removeListener("listening", onlistening);
|
||||||
socket.removeListener("message", onmessage);
|
socket.removeListener("message", onmessage);
|
||||||
socket.removeListener("close", onclose);
|
socket.removeListener("close", onclose);
|
||||||
socket.removeListener("error", onerror);
|
socket.removeListener("error", onerror);
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.addListener("listening", onlistening);
|
socket.addListener("listening", onlistening);
|
||||||
socket.addListener("message", onmessage);
|
socket.addListener("message", onmessage);
|
||||||
socket.addListener("close", onclose);
|
socket.addListener("close", onclose);
|
||||||
socket.addListener("error", onerror);
|
socket.addListener("error", onerror);
|
||||||
|
|
||||||
socket.bind(SSDP_PORT);
|
socket.bind(SSDP_PORT);
|
||||||
|
|
||||||
}
|
}
|
||||||
exports.searchGateway = searchGateway;
|
exports.searchGateway = searchGateway;
|
||||||
|
|
||||||
function Gateway(port, host, path) {
|
function Gateway(port, host, path) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gateway.prototype.getExternalIP = function(callback) {
|
Gateway.prototype.getExternalIP = function(callback) {
|
||||||
|
|
||||||
var s =
|
var s =
|
||||||
"<u:GetExternalIPAddress xmlns:u=\"" + WANIP + "\">\
|
"<u:GetExternalIPAddress xmlns:u=\"" + WANIP + "\">\
|
||||||
</u:GetExternalIPAddress>\n";
|
</u:GetExternalIPAddress>\n";
|
||||||
|
|
||||||
this._getSOAPResponse(s, "GetExternalIPAddress", function(err, xml) {
|
this._getSOAPResponse(s, "GetExternalIPAddress", function(err, xml) {
|
||||||
if (err) callback(err);
|
if (err) callback(err);
|
||||||
else callback(null,
|
else callback(null,
|
||||||
xml.match(/<NewExternalIPAddress>(.+?)<\/NewExternalIPAddress>/i)[1]);
|
xml.match(/<NewExternalIPAddress>(.+?)<\/NewExternalIPAddress>/i)[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gateway.prototype.AddPortMapping = function(protocol
|
Gateway.prototype.AddPortMapping = function(protocol
|
||||||
, extPort
|
, extPort
|
||||||
, intPort
|
, intPort
|
||||||
, host
|
, host
|
||||||
, description
|
, description
|
||||||
, callback) {
|
, callback) {
|
||||||
var s =
|
var s =
|
||||||
"<u:AddPortMapping \
|
"<u:AddPortMapping \
|
||||||
xmlns:u=\""+WANIP+"\">\
|
xmlns:u=\""+WANIP+"\">\
|
||||||
<NewRemoteHost></NewRemoteHost>\
|
<NewRemoteHost></NewRemoteHost>\
|
||||||
<NewExternalPort>"+extPort+"</NewExternalPort>\
|
<NewExternalPort>"+extPort+"</NewExternalPort>\
|
||||||
<NewProtocol>"+protocol+"</NewProtocol>\
|
<NewProtocol>"+protocol+"</NewProtocol>\
|
||||||
<NewInternalPort>"+intPort+"</NewInternalPort>\
|
<NewInternalPort>"+intPort+"</NewInternalPort>\
|
||||||
<NewInternalClient>"+host+"</NewInternalClient>\
|
<NewInternalClient>"+host+"</NewInternalClient>\
|
||||||
<NewEnabled>1</NewEnabled>\
|
<NewEnabled>1</NewEnabled>\
|
||||||
<NewPortMappingDescription>"+description+"</NewPortMappingDescription>\
|
<NewPortMappingDescription>"+description+"</NewPortMappingDescription>\
|
||||||
<NewLeaseDuration>0</NewLeaseDuration>\
|
<NewLeaseDuration>0</NewLeaseDuration>\
|
||||||
</u:AddPortMapping>";
|
</u:AddPortMapping>";
|
||||||
this._getSOAPResponse(s, "AddPortMapping", callback);
|
this._getSOAPResponse(s, "AddPortMapping", callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gateway.prototype._getSOAPResponse = function(soap, func, callback) {
|
Gateway.prototype._getSOAPResponse = function(soap, func, callback) {
|
||||||
var s = [SOAP_ENV_PRE, soap, SOAP_ENV_POST].join("");
|
var s = [SOAP_ENV_PRE, soap, SOAP_ENV_POST].join("");
|
||||||
var client = http.createClient(this.port, this.host);
|
var client = http.createClient(this.port, this.host);
|
||||||
var hdrs = { "host" : this.host
|
var hdrs = { "host" : this.host
|
||||||
, "SOAPACTION" : "\"" + WANIP + "#" + func + "\""
|
, "SOAPACTION" : "\"" + WANIP + "#" + func + "\""
|
||||||
, "content-type" : "text/xml"
|
, "content-type" : "text/xml"
|
||||||
, "content-length" : s.length };
|
, "content-length" : s.length };
|
||||||
var request = client.request("POST", this.path, hdrs);
|
var request = client.request("POST", this.path, hdrs);
|
||||||
request.end(s);
|
request.end(s);
|
||||||
request.addListener('response', function (response) {
|
request.addListener('response', function (response) {
|
||||||
if (response.statusCode !== 200) {
|
if (response.statusCode !== 200) {
|
||||||
response.close();
|
response.close();
|
||||||
callback(new Error("Invalid SOAP action"));
|
callback(new Error("Invalid SOAP action"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var buf = "";
|
var buf = "";
|
||||||
response.addListener('data', function (chunk) { buf += chunk });
|
response.addListener('data', function (chunk) { buf += chunk });
|
||||||
response.addListener('end', function () { callback(null, buf) });
|
response.addListener('end', function () { callback(null, buf) });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,45 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styles from './style.module.css';
|
import styles from './style.module.css';
|
||||||
import { apiRoot } from '../lib/constants.js';
|
import { apiRoot } from '../lib/constants.js';
|
||||||
|
|
||||||
class ActiveConnections extends React.Component {
|
class ActiveConnections extends React.Component {
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
connections: []
|
connections: []
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.refreshData();
|
this.refreshData();
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshData() {
|
async refreshData() {
|
||||||
const req = await fetch(`${apiRoot}/clients`);
|
const req = await fetch(`${apiRoot}/clients`);
|
||||||
const res = await req.json();
|
const res = await req.json();
|
||||||
console.log(res);
|
console.log(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>active connections!</div>
|
<div>active connections!</div>
|
||||||
{this.state.connections.map(connection => {
|
{this.state.connections.map(connection => {
|
||||||
return (<div>
|
return (<div>
|
||||||
{connection.toLocaleString()};
|
{connection.toLocaleString()};
|
||||||
</div>)
|
</div>)
|
||||||
})}
|
})}
|
||||||
<br />
|
<br />
|
||||||
<button onClick={() => this.addConnection.bind(this)()}>
|
<button onClick={() => this.addConnection.bind(this)()}>
|
||||||
Add Connection
|
Add Connection
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addConnection() {
|
addConnection() {
|
||||||
this.state.connections.push(new Date());
|
this.state.connections.push(new Date());
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ActiveConnections;
|
export default ActiveConnections;
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
.red {
|
.red {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,47 @@
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
html {
|
html {
|
||||||
--b1: #001;
|
--b1: #001;
|
||||||
--b2: #112;
|
--b2: #112;
|
||||||
--b3: #223;
|
--b3: #223;
|
||||||
--b4: #334;
|
--b4: #334;
|
||||||
--t1: #EEF;
|
--t1: #EEF;
|
||||||
--t2: #DDE;
|
--t2: #DDE;
|
||||||
--t3: #CCD;
|
--t3: #CCD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
@media (prefers-color-scheme: light) {
|
||||||
html {
|
html {
|
||||||
--b1: #EEF;
|
--b1: #EEF;
|
||||||
--b2: #DDE;
|
--b2: #DDE;
|
||||||
--b3: #CCD;
|
--b3: #CCD;
|
||||||
--b4: #BBC;
|
--b4: #BBC;
|
||||||
--t1: #001;
|
--t1: #001;
|
||||||
--t2: #112;
|
--t2: #112;
|
||||||
--t3: #223;
|
--t3: #223;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background: var(--b1);
|
background: var(--b1);
|
||||||
color: var(--t1);
|
color: var(--t1);
|
||||||
}
|
}
|
||||||
td:not(:last-child), th:not(:last-child) {
|
td:not(:last-child), th:not(:last-child) {
|
||||||
border-right: 1px solid var(--t3);
|
border-right: 1px solid var(--t3);
|
||||||
}
|
}
|
||||||
td, th {
|
td, th {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
th {
|
th {
|
||||||
border-bottom: 3px solid var(--t3);
|
border-bottom: 3px solid var(--t3);
|
||||||
}
|
}
|
||||||
table {
|
table {
|
||||||
border-spacing: 0px;
|
border-spacing: 0px;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
tr:nth-child(2n) {
|
tr:nth-child(2n) {
|
||||||
background: #111;
|
background: #111;
|
||||||
}
|
}
|
||||||
Reference in New Issue