nodejs tcp proxy authentication - node.js

I am using a nodejs module called tcp-proxy to pipe the requests from client to proxy server in order to proxy the requests.
I want this proxy to work only when the user provides the username and password, so I modified my code to make the client send proxy authentication header before proceeding.
Here is my javascript code:
var tcpProxy = require('tcp-proxy');
var server = tcpProxy.createServer({
target: {
host: 'HOST'
port: 'PORT'
}
});
server.listen(8000);
server.on('connection', (socket) => {
socket.on('data', (data) => {
if(!authorized(data, socket)) {
socket.write('HTTP/1.1 407 Proxy Authentication Required\nProxy-Authenticate: Basic realm=""\nConnection: keep-alive');
socket.write('\n\r\n');
socket.end();
}
});
});
function authorized(data, socket) {
if(socket.auth){
return true;
}
for(var i=0; i<=10; i++) {
if(data.toString().split('\r\n')[i]) {
var headerType = data.toString().split('\r\n')[i].split(':')[0];
if(headerType == "Proxy-Authorization") {
var header = data.toString().split('\r\n')[i].split(':')[1];
var creds = new Buffer(header.split(' ')[2], 'base64').toString().split(':');
var username = creds[0];
var password = creds[1];
if(username === "USERNAME" && password === "PASSWORD") {
socket.auth = true;
return true;
} else {
return false;
}
}
}
}
return false;
}
Everything is working fine in Chrome and Mozilla Firefox, but in Safari and some other client applications it doesn't work as expected.
I've tried to debug and found that when making https request from Safari browser (with proxy set in Wifi settings on Mac) the Proxy-Authorization header is missing from the request, and the same happens with the some other client application which have the option to use proxy server.
Since my proxy server is supposed to drop the request if it doesn't find the header it does that for Safari.
Why does this happen? Any solution to get it working on all browsers and applications?

Related

Connecting to offline server with no password but still getting Packet Type of 1 [MINECRAFT]

Currently I am attempting to make a Node.JS implementation for logging into (and interacting with) servers for a future project, and for some reason (even though I have specified that I am connecting to localhost with no password) everytime I send the request, I get a response from the socket with Packet Type 0x01 - despite the documentation (https://wiki.vg) stating:
For unauthenticated ("cracked"/offline-mode) and localhost connections (either of the two conditions is enough for an unencrypted connection) there is no encryption. In that case Login Start is directly followed by Login Success.
My code currently looks like this (incompleted due to this issue arising):
async function Offline(Settings : IClientSettingsParsed) {
const start = Date.now();
let User = Settings.user;
let Server = Settings.server;
const socket = await TCPSocket.connect(Server.host, Server.port);
try {
{
const handshake = new Packet();
handshake.writeVarInt(0x00);
handshake.writeVarInt(Settings.version);
handshake.writeString(Server.host, true);
handshake.writeUShortBE(Server.port);
handshake.writeVarInt(2);
await socket.writePacket(handshake, true);
const start = new Packet();
start.writeVarInt(0x00);
start.writeString(User.username, true);
await socket.writePacket(start, true);
}
const response = await Packet.from(socket);
const type = response.readVarInt();
return type;
} finally {
await socket.dispose();
}
}
it("Should create a new player in offline mode", () => {
let Settings : IClientSettings = {
username: "Bot",
server: {
host: "localhost",
port: 61001,
offline: true
},
version: EVersion["1.8.9"]
}
return Login(Settings).then((result) => {
expect(result).toBe('a');
});
});
Note: they are in different files

Tunnel socket could not established

I am using this package to get the videos from Tiktok tiktok-package.
It's working fine. But now after some time, I could not get any data maybe my IP blocked. So I used proxy for this which gives me error
Error
Exception thrown in tiktok scraper Error: tunneling socket could not be established, cause=getaddrinfo ENOTFOUND http
I run below lines in my project, but still, it's not working
npm config set proxy http://myproxy:port
npm config set https-proxy http://myproxy:port
Code
'use strict';
const TikTokScraper = require('tiktok-scraper');
var main = async(user, numOfVideos) => {
try {
var data = [];
var myPorxy = 'http://proxy_host:port' //my proxy and port
const posts = await TikTokScraper.user(user, { number: numOfVideos, proxy: myPorxy }
);
if (posts) {
posts.collector.map(post => {
data.push(post);
});
}
//return data;
console.log(data);
} catch (error) {
return error;
}
};
main('zachking', 5);
After taking a look at the Options for the packet your are using, it seems like you don't have to specify the protocol if you are using a http proxy:
// Set proxy {string[] | string default: ''}
// http proxy: 127.0.0.1:8080
// socks proxy: socks5://127.0.0.1:8080
// You can pass proxies as an array and scraper will randomly select a proxy from the array to execute the requests
proxy: '',
Assuming everything else is correct var myPorxy = 'proxy_host:port' should work.

Connect to websocket if cloudflare protection is enabled

I am connected to a websocket of some website using node.js and ws module , that usually works fine but recently they re updating something and than they enable cloudflare protection ...
So i get 503 server response when trying to connect
function connect_to_ws(failures) {
if (already_connected) return;
if (failures == undefined) failures = 0;
log('Connecting to "' + ws_server + '"...');
var ws = new WebSocket(ws_server, [], {
'headers': {
'Cookie': cookie
}
});
ws.on('open', function() {
already_connected = true;
log('Connected');
});
...

How to capture http messages from Request Node library with Fiddler

Regular client initiated requests to the node server are captured fine in Fiddler. However, requests sent from node to a web service are not captured. It did not help to pass in config for proxy (127.0.0.1:8888) to the request method. How can I route the request messages through Fiddler?
var http = require('http');
var request = require('request');
request.get(webserviceURL, { "auth" : {"user": "user", "pass" = "pass", sendImmediately: true },
"proxy" : { "host" : "127.0.0.1", "port" : 8888 }},
function (error, response) { console.log( "response received" );
});
Request repo: https://github.com/mikeal/request
I just tried to do this myself (using Fiddler and the request library from npm). Here's how I got it working:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; // Ignore 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' authorization error
// Issue the request
request(
{
method: "GET",
uri: "https://secure.somewebsite.com/",
proxy: "http://127.0.0.1:8888" // Note the fully-qualified path to Fiddler proxy. No "https" is required, even for https connections to outside.
},
function(err, response, body) {
console.log("done");
});
This is with Fiddler2 using the default port and proxy options (and no proxy authentication).
Fiddler works by setting your "Internet Options" (from start menu) "Connections" > "LAN Settings" > "Proxy Server" to its port, thus making all HTTP traffic (clients which obey this setting) go through it.
You should point your node.js client lib to use a proxy, the settings are written in that options dialog after you start Fiddler.
The proxy option should be a full url, like this:
proxy : "http://127.0.0.1:8888"
To do this on an ad-hoc basis, without changing your code, you can use environment variables.
Request respects:
HTTP_PROXY
HTTPS_PROXY
NO_PROXY
So, to proxy just set these in your console before running your process.
For example, to setup http and https proxy use:
set HTTP_PROXY="http://127.0.0.1:8888"
set HTTPS_PROXY="http://127.0.0.1:8888"
set NODE_TLS_REJECT_UNAUTHORIZED=0
The latter line stops issues with SSL through the fiddler proxy.
I've been wanting the same... an equivalent of the Network tab in chrome DevTools, only for Nodejs. Unfortunately, it doesn't appear as though one exists. I don't have Fiddler on macos, so this is how I went about stubbing the require('http') methods to log and pass though. Leaving this here in case I need it again or someone else finds it helpful. You can turn it on by attaching a debugger and require('filename')() the file containing this script.
module.exports = () => {
const http = require('http');
http._request = http.request;
global.DO_LOG_AJAX = true;
const log = str => {
if (global.DO_LOG_AJAX) {
console.debug(str);
}
};
const flushLog = (requestLines, responseLines) => {
if (global.DO_LOG_AJAX) {
log([
'----------------Begin Request-----------------------------------',
...requestLines,
'----------------End Request / Begin Response--------------------',
...responseLines,
'----------------End Reponse-------------------------------------',
].join('\n'));
}
};
let write;
let end;
http.request = (...requestParams) => {
const req = http._request(...requestParams);
const { method, path, headers, host, port } = requestParams[0];
const requestLogLines = [];
requestLogLines.push(`${method} ${path}`);
requestLogLines.push(`Host: ${host}:${port}`);
for (const header of Object.keys(headers)) {
requestLogLines.push(`${header}: ${headers[header]}`);
}
write = write || req.write;
end = end || req.end;
req.on('error', err => {
log({ err });
});
req._write = write;
req._end = end;
const requestBody = [];
req.write = (...writeParams) => {
requestBody.push(writeParams[0].toString());
return req._write(...writeParams);
};
req.end = (...endParams) => {
if (endParams[0]) {
requestBody.push(endParams[0].toString());
}
requestLogLines.push('');
requestLogLines.push(requestBody.join(''));
return req._end(...endParams);
};
const responseLogLines = [];
req.once('response', response => {
const responseBody = [];
responseLogLines.push(`${response.statusCode} ${response.statusMessage}`);
for (const header of Object.keys(response.headers)) {
responseLogLines.push(`${header}: ${response.headers[header]}`);
}
const onData = chunk => {
responseBody.push(chunk.toString());
};
const onClose = err => {
responseLogLines.push('');
responseLogLines.push(responseBody.join(''));
responseLogLines.push('');
responseLogLines.push(`--- ERROR --- ${err.toString()}`);
flushLog(requestLogLines, responseLogLines);
req.removeListener('data', onData);
};
const onEnd = () => {
responseLogLines.push('');
responseLogLines.push(responseBody.join(''));
flushLog(requestLogLines, responseLogLines);
req.removeListener('data', onData);
};
response.on('data', onData);
response.once('close', onClose);
response.once('end', onEnd);
});
return req;
};
};

Node.js redirecting traffic from domain to specific port

so I don't know if this is even possible, but one of my close friends gave me this node.js script that is supposed to do the following:
When someone connects to a Minecraft server with a.FreeMinecraftHost.com:25565 (That's the default port of minecraft, when you have your server running with the default port, clients don't have to type in a port) it is supposed to redirect them to say a.FreeMinecraftHost.com:30000
Here is the code he gave me:
var Socket = require('net').Socket;
var Server = require('net').Server;
var net = require('net');
var SERVERMAP = {
'a.FreeMinecraftHost.com:25565': ['localhost', 30000],
'b.FreeMinecraftHost.com:25565': ['localhost', 30001],
'c.FreeMinecraftHost.com:25565': ['localhost', 30002],
'd.FreeMinecraftHost.com:25565': ['localhost', 30003]
};
var server = new Server();
server.on('connection', function(client) {
var buffer = '';
var authed = false;
client.on('data', function(data) {
if(!authed) buffer += data;
if(!authed) {
var parser = new RegExp('([a-z0-9_]+);([^:]+):([0-9]+)', 'ig');
var parts = parser.exec(buffer.toString().replace(/\0/ig, ''));
if(parts) {
var serverString = parts[2] + ':' + parts[3];
authed=true;
if(SERVERMAP[serverString]) {
var socket = new Socket();
socket.connect(SERVERMAP[serverString][1], SERVERMAP[serverString][0], function() {
socket.write(buffer);
socket.pipe(client);
client.pipe(socket);
});
} else {
client.end();
}
} else {
client.end();
}
}
});
});
The problem is that when I run it, it does nothing, node doesn't keep it alive or anything, I'm just instantly returned to the prompt
EDIT
I got it working! Kind of, I forgot,
server.listen(25565);
at the end, so now I can connect to the Minecraft server and it works, but when the Minecraft Client Pings it in your server list, it shows as offline
What you want to do is to have load balancing i would suggest to do one of two things
a) nginx and proxy pass
upstream minecraft_servers {
server 127.0.0.1:30000;
server 127.0.0.1:30001;
server 127.0.0.1:30002;
server 127.0.0.1:30003;
}
server {
listen 25565;
location / {
proxy_pass http://minecraft_servers;
}
}
b) haproxy loadbalancing
more info here http://haproxy.1wt.eu/

Resources