From 8e18a828b4b9c1b6135bc56de6a7f9ea9aba41c9 Mon Sep 17 00:00:00 2001 From: Glenn Murley Date: Mon, 24 Feb 2014 10:40:18 +0000 Subject: [PATCH] Updated project with INIT script for starting service, and mysql link to get hostname from username. --- README.markdown | 37 +++++++++++++++++- README.md | 4 -- ftp_proxy.js | 71 +++++++++++++++++++++++++++++++++++ test.js => ftp_proxy_blank.js | 44 ++++++++++++---------- ftpmult.js | 2 +- ftpproxy.initscript | 69 ++++++++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 27 deletions(-) delete mode 100644 README.md create mode 100644 ftp_proxy.js rename test.js => ftp_proxy_blank.js (58%) mode change 100755 => 100644 create mode 100644 ftpproxy.initscript diff --git a/README.markdown b/README.markdown index 36753da..6646b87 100644 --- a/README.markdown +++ b/README.markdown @@ -6,6 +6,10 @@ ftpmult - a simple FTP multiplexer / reverse proxy written in Node.JS Welcome ---- +THIS IS A FORK OF https://github.com/peter-x/ftpmult + +IMPROVED BY https://github.com/djpimp2010/ftpmult + This piece of software provides a reverse proxy for FTP which can select the target server based on the username. This is for example useful in a hosting environment where you have many virtual servers but only a single IP address and @@ -15,10 +19,39 @@ all or only based on some suffix ("`@hostname`") of the username. Furthermore, ftpmult is an extremely simple piece of software (less than 300 lines) and can thus be easily adapted to your needs. +THIS SERVICE INIT SCRIPT HAS BEEN DESIGNED ON THE PRETENSE THAT NODE JS ONLY RUNS FOR THIS PROGRAM +IF YOU HAVE OTHER PROGRAMS RUNNING NODE.JS YOU WILL NEED TO IMPROVE THE SERVICE INIT SCRIPT + How to use ---- -See `test.js` for an example and adjust the callback `getHostFromUsername` to your -needs. +(THIS GUIDE IS BASED ON CentOS/Fedora) + +1. Once the repo is cloned into your node.js modules directory, you will need to copy 'ftpproxy.initscript' to /etc/init.d + (Or your 'service' script location, for other distros) + +2. Edit ftpproxy.initscript and set the two variables at the top: + NODE_EXECUTABLE_PATH=/usr/local/bin/node + NODE_MODULES_PATH=/usr/local/bin/lib/node_modules/npm/node_modules + +3. Rename file from ftpproxy.initscript to ftpproxy, and chmod with executable permissions for root. + +4. Decide if you are going to be using a database to manage users/hosts. + If you are, the database must have these fields: + 'increment_name' (primary key, auto increment) *name can vary* + 'username' (varchar) + 'host' (varchar) + + You can have other fields too, as long as each row is unique, and the fields username and host are present. + This could be linked into a pre-existent user management database. + +5. If you are using a database to manage users, and your database is set up, you should be ready to test the script. + # service ftpproxy start + If there are any errors, they will be listed in the console window. + If you see the message "FTP multiplexer up and ready for connections." then your server is listening. + +If you decided not to use mysql to manage users, please rename 'ftp_proxy.js' to 'ftp_proxy.js.old', +And then rename 'ftp_proxy_blank.js' to 'ftp_proxy.js' +This is a template file for creating a proxy server, although this has no function written for getting hostname from username. diff --git a/README.md b/README.md deleted file mode 100644 index 9d11446..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -ftpmult -======= - -Simple FTP multiplexer / reverse proxy using Node.js \ No newline at end of file diff --git a/ftp_proxy.js b/ftp_proxy.js new file mode 100644 index 0000000..e808ed4 --- /dev/null +++ b/ftp_proxy.js @@ -0,0 +1,71 @@ +var ftpd = require('./ftpmult.js'); + +/*function to check associative array for username, and return host*/ +/*if username is not in array, return bad host, so that connection is refused*/ +/*array example: + users = [ + { record_id: "1", username: "testuser1", host: "192.168.0.11" }, + { record_id: "2", username: "testuser2", host: "192.168.0.12" }, + { record_id: "3", username: "testuser3", host: "192.168.0.13" } + ];*/ +Array.prototype.contains = function ( needle ) { + for (i in this) { + if (this[i]['username'] === needle) return this[i]['host']; + } + return '10.32.0.1'; /*set this to an IP address not in your network*/ +} + +/*node.js mysql library required*/ +/*npm install mysql*/ +var mysql = require('mysql'); +var connection = mysql.createConnection({ + host : '192.168.0.10', + user : 'ftpproxy', + password: 'P4ssw0rd', + database: 'ftpproxy' +}); + +/*connect once on service start, and run query to get users*/ +connection.connect(function(err){ + if(err){ + console.log(err); + return; + } +}); + +/*this query fetches all users from the table ftpproxy.users*/ +connection.query('SELECT * from users', function(err, rows, fields) { + if (err) { + console.log(err); + return; + } else { + /*store array in global scope, without declaring it as a 'var'*/ + users = rows; + } +}); + +/*close mysql connection, as we now have array of users*/ +connection.end(); + +/*create server on ftp login attempt*/ +var server = new ftpd.FtpServer({ + getHostFromUsername: function(username) { + var host = users.contains(username); + return {hostname: host, port: 21} + } +}); + +server.logLevel = 4; +/*listen on port 21 (command issued as root)*/ +server.listen(21); +try { + /*change uid/gid to non-root user*/ + process.setuid(65534); + process.setgid(65534); +} catch (e) { +} +server.server.on("error", function() { + /* better exit so that someone can restart us */ + process.exit(1); +}); + diff --git a/test.js b/ftp_proxy_blank.js old mode 100755 new mode 100644 similarity index 58% rename from test.js rename to ftp_proxy_blank.js index d3de3e9..9009ca2 --- a/test.js +++ b/ftp_proxy_blank.js @@ -1,20 +1,24 @@ -var ftpd = require('./ftpmult.js'); - -try { - process.setuid(65534); - process.setgid(65534); -} catch (e) { -} - -var server = new ftpd.FtpServer({ - getHostFromUsername: function(username) { - return {hostname: 'ftp.kernel.org', port: 21}; - } -}); - -server.logLevel = 4; -server.listen(7002); -server.server.on("error", function() { - /* better exit so that someone can restart us */ - process.exit(1); -}); +var ftpd = require('./ftpmult.js'); + +/*create server on ftp login attempt*/ +var server = new ftpd.FtpServer({ + getHostFromUsername: function(username) { + /*insert code here to determine hostname from username*/ + return {hostname: "192.168.0.20", port: 21} + } +}); + +server.logLevel = 4; +/*listen on port 21 (command issued as root)*/ +server.listen(21); +try { + /*change uid/gid to non-root user*/ + process.setuid(65534); + process.setgid(65534); +} catch (e) { +} +server.server.on("error", function() { + /* better exit so that someone can restart us */ + process.exit(1); +}); + diff --git a/ftpmult.js b/ftpmult.js index 55c1e81..1d2890b 100644 --- a/ftpmult.js +++ b/ftpmult.js @@ -9,7 +9,7 @@ function FtpServer(options) { return new FtpServer(options); } - this.myHost = options.host || '127.0.0.1'; + this.myHost = options.host || '127.0.0.1'; // I had to change this to my FTP Proxy server IP of 192.168.0.100 this.server = net.createServer(); this.getHostFromUsername = options.getHostFromUsername || function(username) { return null; }; this.logLevel = options.logLevel || 0; diff --git a/ftpproxy.initscript b/ftpproxy.initscript new file mode 100644 index 0000000..a87e60c --- /dev/null +++ b/ftpproxy.initscript @@ -0,0 +1,69 @@ +#!/bin/sh + +# chkconfig: 345 70 30 +# description: ftpproxy +# processname: ftpproxy + +NODE_EXECUTABLE_PATH=/usr/local/bin/node +NODE_MODULES_PATH=/usr/local/bin/lib/node_modules/npm/node_modules + +check () { + if pidof -x "node" >/dev/null; then + return 0 + else + return 1 + fi +} + +chk_status () { + if check; then + echo "FTP Proxy is running" + echo + else + echo "FTP Proxy is stopped" + echo + fi +} + +start () { + if check; then + echo "FTP Proxy is already running" + echo + else + echo "Starting FTP Proxy" + $NODE_EXECUTABLE_PATH $NODE_MODULES_PATH/ftpmult/ftp_proxy.js & + chk_status + touch /var/lock/subsys/ftpproxy + fi +} + +stop () { + if check; then + echo "Stopping FTP Proxy" + pkill -9 node + rm -rf /var/lock/subsys/ftpproxy + chk_status + else + echo "FTP Proxy is not running" + echo + fi +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + chk_status + ;; + *) + echo $"Usage: $0 {start|stop|restart|status}" +esac +