From ed425e775d7fee39cf33c414d8e0c73fa0857ebe Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Thu, 13 Jul 2017 14:42:42 +0200 Subject: [PATCH 1/6] add 2 examples : client_http_proxy and client_socks_proxy. fix #185 fix #436 --- .gitignore | 1 + .../client_http_proxy/client_http_proxy.js | 46 +++++++++++++++++++ examples/client_http_proxy/package.json | 8 ++++ .../client_socks_proxy/client_socks_proxy.js | 40 ++++++++++++++++ examples/client_socks_proxy/package.json | 9 ++++ 5 files changed, 104 insertions(+) create mode 100644 examples/client_http_proxy/client_http_proxy.js create mode 100644 examples/client_http_proxy/package.json create mode 100644 examples/client_socks_proxy/client_socks_proxy.js create mode 100644 examples/client_socks_proxy/package.json diff --git a/.gitignore b/.gitignore index be85d62..b603449 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules test/npm-debug.log test/server +package-lock.json diff --git a/examples/client_http_proxy/client_http_proxy.js b/examples/client_http_proxy/client_http_proxy.js new file mode 100644 index 0000000..703619a --- /dev/null +++ b/examples/client_http_proxy/client_http_proxy.js @@ -0,0 +1,46 @@ +const mc = require('minecraft-protocol'); +const Http = require("http"); + +if(process.argv.length < 6 || process.argv.length > 8) { + console.log("Usage : node echo.js [] []"); + process.exit(1); +} + +const proxyHost=process.argv[4]; +const proxyPort=process.argv[5]; + +const req = Http.request({ + host: proxyHost, + port: proxyPort, + method: 'CONNECT', + path: process.argv[2] + ":" + parseInt(process.argv[3]) +}); + +req.on("connect", function(res, stream) { + const client = mc.createClient({ + stream: stream, + username: process.argv[6] ? process.argv[6] : "echo", + password: process.argv[7] + }); + + client.on('connect', function() { + console.info('connected'); + }); + client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); + }); + client.on('end', function(err) { + console.log('Connection lost'); + }); + client.on('chat', function(packet) { + const jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { + const username = jsonMsg.with[0].text; + const msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } + }); + +}); + diff --git a/examples/client_http_proxy/package.json b/examples/client_http_proxy/package.json new file mode 100644 index 0000000..56fcdf2 --- /dev/null +++ b/examples/client_http_proxy/package.json @@ -0,0 +1,8 @@ +{ + "name": "node-minecraft-protocol-example", + "version": "0.0.0", + "private": true, + "dependencies": { + }, + "description": "A node-minecraft-protocol example" +} diff --git a/examples/client_socks_proxy/client_socks_proxy.js b/examples/client_socks_proxy/client_socks_proxy.js new file mode 100644 index 0000000..1dc9c6b --- /dev/null +++ b/examples/client_socks_proxy/client_socks_proxy.js @@ -0,0 +1,40 @@ +const mc = require('minecraft-protocol'); +const Socks = require("socks5-client"); + +if(process.argv.length < 6 || process.argv.length > 8) { + console.log("Usage : node echo.js [] []"); + process.exit(1); +} + +const proxyHost=process.argv[4]; +const proxyPort=process.argv[5]; + +const client = mc.createClient({ + stream: Socks.createConnection({ + host: process.argv[2], + port: parseInt(process.argv[3]), + socksHost: proxyHost, + socksPort: proxyPort + }), + username: process.argv[6] ? process.argv[6] : "echo", + password: process.argv[7] +}); + +client.on('connect', function() { + console.info('connected'); +}); +client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); +}); +client.on('end', function(err) { + console.log('Connection lost'); +}); +client.on('chat', function(packet) { + const jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { + const username = jsonMsg.with[0].text; + const msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } +}); diff --git a/examples/client_socks_proxy/package.json b/examples/client_socks_proxy/package.json new file mode 100644 index 0000000..e9cd5bd --- /dev/null +++ b/examples/client_socks_proxy/package.json @@ -0,0 +1,9 @@ +{ + "name": "node-minecraft-protocol-example", + "version": "0.0.0", + "private": true, + "dependencies": { + "socks5-client": "^1.2.5" + }, + "description": "A node-minecraft-protocol example" +} From d8844a5ba1a5a16a1d789679ad82f9e0e9dd5715 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Mon, 17 Jul 2017 15:30:00 +0200 Subject: [PATCH 2/6] Update client_http_proxy.js --- examples/client_http_proxy/client_http_proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/client_http_proxy/client_http_proxy.js b/examples/client_http_proxy/client_http_proxy.js index 703619a..8a98d13 100644 --- a/examples/client_http_proxy/client_http_proxy.js +++ b/examples/client_http_proxy/client_http_proxy.js @@ -2,7 +2,7 @@ const mc = require('minecraft-protocol'); const Http = require("http"); if(process.argv.length < 6 || process.argv.length > 8) { - console.log("Usage : node echo.js [] []"); + console.log("Usage : node client_http_proxy.js [] []"); process.exit(1); } From e9ced90a507f713d5d7ac1d64febd6ebbafaeab0 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Mon, 17 Jul 2017 15:30:14 +0200 Subject: [PATCH 3/6] Update client_socks_proxy.js --- examples/client_socks_proxy/client_socks_proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/client_socks_proxy/client_socks_proxy.js b/examples/client_socks_proxy/client_socks_proxy.js index 1dc9c6b..b6a7e72 100644 --- a/examples/client_socks_proxy/client_socks_proxy.js +++ b/examples/client_socks_proxy/client_socks_proxy.js @@ -2,7 +2,7 @@ const mc = require('minecraft-protocol'); const Socks = require("socks5-client"); if(process.argv.length < 6 || process.argv.length > 8) { - console.log("Usage : node echo.js [] []"); + console.log("Usage : node client_socks_proxy.js [] []"); process.exit(1); } From cab5a329bf9e955131eac5c709244923c20f2eda Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Wed, 19 Jul 2017 16:41:07 +0200 Subject: [PATCH 4/6] fix http proxy --- examples/client_http_proxy/client_http_proxy.js | 1 + src/client/tcp_dns.js | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/client_http_proxy/client_http_proxy.js b/examples/client_http_proxy/client_http_proxy.js index 8a98d13..ff72db3 100644 --- a/examples/client_http_proxy/client_http_proxy.js +++ b/examples/client_http_proxy/client_http_proxy.js @@ -15,6 +15,7 @@ const req = Http.request({ method: 'CONNECT', path: process.argv[2] + ":" + parseInt(process.argv[3]) }); +req.end(); req.on("connect", function(res, stream) { const client = mc.createClient({ diff --git a/src/client/tcp_dns.js b/src/client/tcp_dns.js index f0b5c33..834610a 100644 --- a/src/client/tcp_dns.js +++ b/src/client/tcp_dns.js @@ -8,6 +8,7 @@ module.exports = function(client, options) { options.connect = (client) => { if (options.stream) { client.setSocket(options.stream); + client.emit('connect'); } else if (options.port == 25565 && net.isIP(options.host) === 0) { dns.resolveSrv("_minecraft._tcp." + options.host, function(err, addresses) { if(addresses && addresses.length > 0) { From 6279ae9afe6679d23d02a9cf1160e89caac3e0a7 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Wed, 19 Jul 2017 17:24:51 +0200 Subject: [PATCH 5/6] fix socks proxy using a socks module that actually works and provide a proper node stream --- .../client_socks_proxy/client_socks_proxy.js | 66 +++++++++++-------- examples/client_socks_proxy/package.json | 2 +- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/examples/client_socks_proxy/client_socks_proxy.js b/examples/client_socks_proxy/client_socks_proxy.js index b6a7e72..4108e8c 100644 --- a/examples/client_socks_proxy/client_socks_proxy.js +++ b/examples/client_socks_proxy/client_socks_proxy.js @@ -1,5 +1,5 @@ const mc = require('minecraft-protocol'); -const Socks = require("socks5-client"); +const socks = require("socks"); if(process.argv.length < 6 || process.argv.length > 8) { console.log("Usage : node client_socks_proxy.js [] []"); @@ -9,32 +9,44 @@ if(process.argv.length < 6 || process.argv.length > 8) { const proxyHost=process.argv[4]; const proxyPort=process.argv[5]; -const client = mc.createClient({ - stream: Socks.createConnection({ +socks.createConnection({ + proxy: { + ipaddress: proxyHost, + port: proxyPort, + type: 5 + }, + target: { host: process.argv[2], - port: parseInt(process.argv[3]), - socksHost: proxyHost, - socksPort: proxyPort - }), - username: process.argv[6] ? process.argv[6] : "echo", - password: process.argv[7] + port: parseInt(process.argv[3]) + }, +}, function(err, socket) { + if (err) { + console.log(err); + return; + } + const client = mc.createClient({ + stream: socket, + username: process.argv[6] ? process.argv[6] : "echo", + password: process.argv[7] + }); + + client.on('connect', function() { + console.info('connected'); + }); + client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); + }); + client.on('end', function(err) { + console.log('Connection lost'); + }); + client.on('chat', function(packet) { + const jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { + const username = jsonMsg.with[0].text; + const msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } + }); }); -client.on('connect', function() { - console.info('connected'); -}); -client.on('disconnect', function(packet) { - console.log('disconnected: '+ packet.reason); -}); -client.on('end', function(err) { - console.log('Connection lost'); -}); -client.on('chat', function(packet) { - const jsonMsg = JSON.parse(packet.message); - if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { - const username = jsonMsg.with[0].text; - const msg = jsonMsg.with[1]; - if(username === client.username) return; - client.write('chat', {message: msg}); - } -}); diff --git a/examples/client_socks_proxy/package.json b/examples/client_socks_proxy/package.json index e9cd5bd..95671a6 100644 --- a/examples/client_socks_proxy/package.json +++ b/examples/client_socks_proxy/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "dependencies": { - "socks5-client": "^1.2.5" + "socks": "^1.1.10" }, "description": "A node-minecraft-protocol example" } From 010362ef7823225eb5f2b018d74e593df75b77c0 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Wed, 19 Jul 2017 18:39:25 +0200 Subject: [PATCH 6/6] add connect option to createClient for multiple (ping + normal) connections for the proxy examples, use the normal options for pinging in autoVersion to have that option available and fix the proxy examples accordingly --- doc/README.md | 3 + .../client_http_proxy/client_http_proxy.js | 66 ++++++++-------- examples/client_http_proxy/package.json | 3 +- .../client_socks_proxy/client_socks_proxy.js | 79 ++++++++++--------- src/client/autoVersion.js | 3 +- src/client/tcp_dns.js | 3 +- 6 files changed, 82 insertions(+), 75 deletions(-) diff --git a/doc/README.md b/doc/README.md index b650d44..a023bde 100644 --- a/doc/README.md +++ b/doc/README.md @@ -21,6 +21,9 @@ automatically logged in and validated against mojang's auth. * customPackets (optional) : an object index by version/state/direction/name, see client_custom_packet for an example * errorHandler : A way to override the default error handler for client errors. A function that takes a Client and an error. The default kicks the client. + * stream : a stream to use as connection + * connect : a function taking the client as parameter and that should client.setSocket(socket) + and client.emit('connect') when appropriate (see the proxy examples for an example of use) ## mc.Server(version,[customPackets]) diff --git a/examples/client_http_proxy/client_http_proxy.js b/examples/client_http_proxy/client_http_proxy.js index ff72db3..68e5185 100644 --- a/examples/client_http_proxy/client_http_proxy.js +++ b/examples/client_http_proxy/client_http_proxy.js @@ -9,39 +9,41 @@ if(process.argv.length < 6 || process.argv.length > 8) { const proxyHost=process.argv[4]; const proxyPort=process.argv[5]; -const req = Http.request({ - host: proxyHost, - port: proxyPort, - method: 'CONNECT', - path: process.argv[2] + ":" + parseInt(process.argv[3]) -}); -req.end(); +const client = mc.createClient({ + connect:(client) => { + const req = Http.request({ + host: proxyHost, + port: proxyPort, + method: 'CONNECT', + path: process.argv[2] + ":" + parseInt(process.argv[3]) + }); + req.end(); -req.on("connect", function(res, stream) { - const client = mc.createClient({ - stream: stream, + req.on("connect", function(res, stream) { + client.setSocket(stream); + client.emit('connect'); + }); + }, username: process.argv[6] ? process.argv[6] : "echo", - password: process.argv[7] - }); - - client.on('connect', function() { - console.info('connected'); - }); - client.on('disconnect', function(packet) { - console.log('disconnected: '+ packet.reason); - }); - client.on('end', function(err) { - console.log('Connection lost'); - }); - client.on('chat', function(packet) { - const jsonMsg = JSON.parse(packet.message); - if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { - const username = jsonMsg.with[0].text; - const msg = jsonMsg.with[1]; - if(username === client.username) return; - client.write('chat', {message: msg}); - } - }); - + password: process.argv[7] +}); + +client.on('connect', function() { + console.info('connected'); +}); +client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); +}); +client.on('end', function(err) { + console.log('Connection lost'); +}); +client.on('chat', function(packet) { + const jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { + const username = jsonMsg.with[0].text; + const msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } }); diff --git a/examples/client_http_proxy/package.json b/examples/client_http_proxy/package.json index 56fcdf2..15ca434 100644 --- a/examples/client_http_proxy/package.json +++ b/examples/client_http_proxy/package.json @@ -2,7 +2,6 @@ "name": "node-minecraft-protocol-example", "version": "0.0.0", "private": true, - "dependencies": { - }, + "dependencies": {}, "description": "A node-minecraft-protocol example" } diff --git a/examples/client_socks_proxy/client_socks_proxy.js b/examples/client_socks_proxy/client_socks_proxy.js index 4108e8c..383cc5a 100644 --- a/examples/client_socks_proxy/client_socks_proxy.js +++ b/examples/client_socks_proxy/client_socks_proxy.js @@ -9,44 +9,47 @@ if(process.argv.length < 6 || process.argv.length > 8) { const proxyHost=process.argv[4]; const proxyPort=process.argv[5]; -socks.createConnection({ - proxy: { - ipaddress: proxyHost, - port: proxyPort, - type: 5 - }, - target: { - host: process.argv[2], - port: parseInt(process.argv[3]) - }, -}, function(err, socket) { - if (err) { - console.log(err); - return; - } - const client = mc.createClient({ - stream: socket, - username: process.argv[6] ? process.argv[6] : "echo", - password: process.argv[7] - }); +const client = mc.createClient({ + connect: client => { + socks.createConnection({ + proxy: { + ipaddress: proxyHost, + port: proxyPort, + type: 5 + }, + target: { + host: process.argv[2], + port: parseInt(process.argv[3]) + }, + }, function(err, socket) { + if (err) { + console.log(err); + return; + } - client.on('connect', function() { - console.info('connected'); - }); - client.on('disconnect', function(packet) { - console.log('disconnected: '+ packet.reason); - }); - client.on('end', function(err) { - console.log('Connection lost'); - }); - client.on('chat', function(packet) { - const jsonMsg = JSON.parse(packet.message); - if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { - const username = jsonMsg.with[0].text; - const msg = jsonMsg.with[1]; - if(username === client.username) return; - client.write('chat', {message: msg}); - } - }); + client.setSocket(socket); + client.emit('connect'); + }); + }, + username: process.argv[6] ? process.argv[6] : "echo", + password: process.argv[7] }); +client.on('connect', function() { + console.info('connected'); +}); +client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); +}); +client.on('end', function(err) { + console.log('Connection lost'); +}); +client.on('chat', function(packet) { + const jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate === 'chat.type.announcement' || jsonMsg.translate === 'chat.type.text') { + const username = jsonMsg.with[0].text; + const msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } +}); diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 23293cb..71f435a 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -9,9 +9,8 @@ const minecraft_data = require('minecraft-data'); module.exports = function(client, options) { client.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' debug('pinging',options.host); - const pingOptions = {host: options.host, port: options.port}; // TODO: use 0xfe ping instead for better compatibility/performance? https://github.com/deathcap/node-minecraft-ping - ping(pingOptions, function(err, response) { + ping(options, function(err, response) { if (err) throw err; // hmm debug('ping response',response); // TODO: could also use ping pre-connect to save description, type, max players, etc. diff --git a/src/client/tcp_dns.js b/src/client/tcp_dns.js index 834610a..110e4f8 100644 --- a/src/client/tcp_dns.js +++ b/src/client/tcp_dns.js @@ -5,7 +5,8 @@ module.exports = function(client, options) { options.port = options.port || 25565; options.host = options.host || 'localhost'; - options.connect = (client) => { + if(!options.connect) + options.connect = (client) => { if (options.stream) { client.setSocket(options.stream); client.emit('connect');