Skip to content

Commit 5708ed4

Browse files
author
Jean-Tiare Le Bigot
committed
added basic authentication, see readme.txt + some small cleanup
1 parent c425987 commit 5708ed4

File tree

2 files changed

+69
-13
lines changed

2 files changed

+69
-13
lines changed

config/readme.txt

+17-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ priority :
2323
1) redirect => will issue a 301 to the browser
2424
2) proxyto => will lead to a "regular" reverse proxying
2525
3) default is to proxy
26+
Note that user authentication is *always* performed **before**. See bellow for
27+
more informations on athentication
28+
29+
It is also possible to specify authorization criterion. This is done using the
30+
"Basic" http authentication scheme as defined in RFC 2617. "Digest" is not (yet ?)
31+
supported. Since this reverse proxy is not seen by the useragent as a real proxy,
32+
we can not use proxy-authenticate. This is sad because it prevents you from dong
33+
http authentication on the other side as soon as you do not use the same credentials.
34+
Passwords SHALL be written un-encrypted at the moment.
35+
If you are planing on doing authentication on the application side, please do not
36+
use this feature as it will break it !
2637

2738
NOTA: only http is supported, no HTTPS yet
2839

@@ -32,7 +43,12 @@ example:
3243
"redirect": "www.google.com"
3344
},
3445
"*:80":{
35-
"proxyto": "localhost:80"
46+
"proxyto": "localhost:80",
47+
"validuser":{
48+
"admin":"pasword",
49+
"user":"secret"
50+
},
51+
"description":"Very secret project here ;-)"
3652
}
3753
}
3854

proxy.js

+52-12
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function update_list(msg, file, mapf, collectorf) {
4343
sys.log(msg);
4444
fs.readFile(file, function(err, data) {
4545
collectorf(data.toString().split("\n")
46-
.filter(function(rx) { return rx.length })
46+
.filter(function(rx){return rx.length;})
4747
.map(mapf));
4848
});
4949
}
@@ -74,17 +74,17 @@ function update_blacklist() {
7474
update_list(
7575
"Updating host black list.",
7676
config.black_list,
77-
function(rx) { return RegExp(rx) },
78-
function(list) { blacklist = list }
77+
function(rx){return RegExp(rx);},
78+
function(list){blacklist = list;}
7979
);
8080
}
8181

8282
function update_iplist() {
8383
update_list(
8484
"Updating allowed ip list.",
8585
config.allow_ip_list,
86-
function(ip){return ip},
87-
function(list) { iplist = list }
86+
function(ip){return ip;},
87+
function(list){iplist = list;}
8888
);
8989
}
9090

@@ -98,11 +98,38 @@ function host_allowed(host) {
9898
return !blacklist.some(function(host_) { return host_.test(host); });
9999
}
100100

101+
//header decoding
102+
function authenticate(request){
103+
token={
104+
"login":"anonymous",
105+
"pass":""
106+
};
107+
if (request.headers.authorization && request.headers.authorization.search('Basic ') === 0) {
108+
// fetch login and password
109+
basic = (new Buffer(request.headers.authorization.split(' ')[1], 'base64').toString());
110+
sys.log("Authentication token received: "+basic);
111+
basic = basic.split(':');
112+
token.login = basic[0];
113+
token.pass = basic[1];//fixme: potential trouble if there is a ":" in the pass
114+
}
115+
return token;
116+
}
117+
101118
//proxying
102119
//handle 2 rules:
103120
// * redirect (301)
104121
// * proxyto
105-
function handle_proxy_rule(rule, target){
122+
function handle_proxy_rule(rule, target, token){
123+
//handle authorization
124+
if("validuser" in rule){
125+
if(!(token.login in rule.validuser) || (rule.validuser[token.login] != token.pass)){
126+
target.action = "authenticate";
127+
target.msg = rule.description || "";
128+
return target;
129+
}
130+
}
131+
132+
//handle real acions
106133
if("redirect" in rule){
107134
target = hosthelper(rule.redirect);
108135
target.action = "redirect";
@@ -113,24 +140,24 @@ function handle_proxy_rule(rule, target){
113140
return target;
114141
}
115142

116-
function host_filter(host) {
143+
function host_filter(host, token) {
117144
//extract target host and port
118145
action = hosthelper(host);
119146
action.action="proxyto";
120147

121148
//try to find a matching rule
122149
if(action.host+':'+action.port in hostfilters){
123150
rule=hostfilters[action.host+':'+action.port];
124-
action=handle_proxy_rule(rule, action);
151+
action=handle_proxy_rule(rule, action, token);
125152
}else if (action.host in hostfilters){
126153
rule=hostfilters[action.host];
127-
action=handle_proxy_rule(rule, action);
154+
action=handle_proxy_rule(rule, action, token);
128155
}else if ("*:"+action.port in hostfilters){
129156
rule=hostfilters['*:'+action.port];
130-
action=handle_proxy_rule(rule, action);
157+
action=handle_proxy_rule(rule, action, token);
131158
}else if ("*" in hostfilters){
132159
rule=hostfilters['*'];
133-
action=handle_proxy_rule(rule, action);
160+
action=handle_proxy_rule(rule, action, token);
134161
}
135162
return action;
136163
}
@@ -148,6 +175,13 @@ function prevent_loop(request, response){
148175
}
149176
}
150177

178+
function action_authenticate(response, msg){
179+
response.writeHead(401,{
180+
'WWW-Authenticate': "Basic realm=\""+msg+"\""
181+
});
182+
response.end();
183+
}
184+
151185
function action_deny(response, msg) {
152186
response.writeHead(403);
153187
response.write(msg);
@@ -225,19 +259,25 @@ function server_cb(request, response) {
225259

226260
sys.log(ip + ": " + request.method + " " + request.url);
227261

262+
//get authorization token
263+
authorization = authenticate(request);
264+
228265
//calc new host info
229-
var action = host_filter(request.headers.host);
266+
var action = host_filter(request.headers.host, authorization);
230267
host = hostporthelper(action);
231268

232269
//handle action
233270
if(action.action == "redirect"){
234271
action_redirect(response, host);
235272
}else if(action.action == "proxyto"){
236273
action_proxy(response, request, host);
274+
} else if(action.action == "authenticate"){
275+
action_authenticate(response, action.msg);
237276
}
238277
}
239278

240279
//last chance error handler
280+
//de-comment it in a production env for more stability :)
241281
/*process.on('uncaughtException', function (err) {
242282
console.log('LAST ERROR: Caught exception: ' + err);
243283
});*/

0 commit comments

Comments
 (0)