shithub: tcp80

Download patch

ref: 55fd68b490df201222f81e06bd461c572b7828d7
parent: 13d9eb9e6470da1c9a5656438c80ea3d14680b6d
author: igor <igor@mux>
date: Fri Sep 16 16:14:52 EDT 2022

Do not load /lib/namespace.httpd; improve logging and matching.

--- /dev/null
+++ b/README.md
@@ -1,0 +1,11 @@
+Yet another tcp80 implementation…
+
+…it only serves static files, and enables one
+to block agents and requests that match patterns.
+
+This enables one to simply drop any connections
+that attempt to access PHP, CGI, etc. files.
+
+One can also block based on agent name enabling
+one to drop certain services performing automated
+security vulnerability scans…
--- a/tcp80.c
+++ b/tcp80.c
@@ -4,42 +4,61 @@
 #include <auth.h>
 #include <regexp.h>
 
+typedef struct Host Host;
 typedef struct Pair Pair;
+typedef struct Rule Rule;
+
+struct Host
+{
+	char	*domain;	/* domain pattern */
+	char	*root;		/* document root */
+};
+
 struct Pair
 {
 	Pair	*next;
-
 	char	key[64];
 	char	val[256];
-	char	*att;
 };
 
-typedef struct Rule Rule;
+enum
+{
+	None = 0,
+	Drop = 1<<None,
+	Log  = 1<<Drop
+};
+
 struct Rule
 {
-	char *pat;
-	char *rul;
+	char	*pat;
+	int		act;
 };
 
 char remote[128];
 char method[64];
 char location[1024];
+char proto[16];
 
 Pair *header;
 int naheader;
 Pair aheader[64];
 
-Rule hostrules[] = {
-	"bytelabs.mux.9lab.org",	"/usr/igor/www/bytelabs",
-	"mux.9lab.org",	"/usr/igor/www/9lab/public",
+char *host;
+char *referer;
+char *useragent;
+
+Host hosts[] = {
+	/* domain,									root */
+	{ "(www\.)?bytelabs\.(mux\.9lab\.)?org",	"/usr/igor/www/bytelabs"	},
+	{ "((www|mux)\.)?9lab\.org",				"/usr/igor/www/9lab/public"	}
 };
 
 Rule blockrules[] = {
-	".*\\.(php|cgi|asp|jsp|cfm|pl)(\\?.*)?$",	"DROP",
+	{ ".*\\.(php|cgi|asp|jsp|cfm|pl)(\\?.*)?$",	Drop	}
 };
 
 Rule blockagents[] = {
-	".*cyberscan\\.io.*", "DROP",
+	{ ".*cyberscan\\.io.*", Drop	}
 };
 
 Pair*
@@ -56,15 +75,17 @@
 }
 
 char*
-hostrule(char *host)
+findhost(char *host)
 {
 	int i;
 	Reprog *re;
 
-	for(i = 0; i < nelem(hostrules); i++){
-		if(re = regcomp(hostrules[i].pat)){
+	if(host == nil)
+		return nil;
+	for(i = 0; i < nelem(hosts); i++){
+		if(re = regcomp(hosts[i].domain)){
 			if(regexec(re, host, 0, 0)){
-				return hostrules[i].rul;
+				return hosts[i].root;
 			}
 		}
 	}
@@ -71,36 +92,40 @@
 	return nil;
 }
 
-char*
+int
 blockrule(char *path)
 {
 	int i;
 	Reprog *re;
 
+	if(path == nil)
+		return None;
 	for(i = 0; i < nelem(blockrules); i++){
 		if(re = regcomp(blockrules[i].pat)){
 			if(regexec(re, path, 0, 0)){
-				return blockrules[i].rul;
+				return blockrules[i].act;
 			}
 		}
 	}
-	return nil;
+	return None;
 }
 
-char*
+int
 blockagent(char *agent)
 {
 	int i;
 	Reprog *re;
 
+	if(agent == nil)
+		return None;
 	for(i = 0; i < nelem(blockagents); i++){
 		if(re = regcomp(blockagents[i].pat)){
 			if(regexec(re, agent, 0, 0)){
-				return blockagents[i].rul;
+				return blockagents[i].act;
 			}
 		}
 	}
-	return nil;
+	return None;
 }
 
 char*
@@ -110,6 +135,17 @@
 	return strncpy(d, s, n-1);
 }
 
+void
+savehdr(Pair *h)
+{
+	if(cistrcmp(h->key, "Host") == 0)
+		host = h->val;
+	else if(cistrcmp(h->key, "Referer") == 0)
+		referer = h->val;
+	else if(cistrcmp(h->key, "User-Agent") == 0)
+		useragent = h->val;
+}
+
 char hex[] = "0123456789ABCDEF";
 
 char*
@@ -308,7 +344,10 @@
 void
 respond(char *status)
 {
-	syslog(0, "tcp80", "%s %s %s %s", remote, method, location, status);
+	syslog(0, "tcp80", "%s %s %s %s %s [%s] [%s] %s",
+		remote, host, method, location, proto,
+		referer ? referer : "", useragent ? useragent : "",
+		status);
 	print("HTTP/1.1 %s\r\n", status);
 }
 
@@ -390,9 +429,8 @@
 			respond(status);
 			headers(buf, d);
 
-			h = findhdr(nil, "Host");
 			p = strchr(location, '?');
-			s = fullurl(h ? h->val : nil, urlenc(tmp, buf, sizeof(tmp)), "/", p ? p+1 : nil);
+			s = fullurl(host, urlenc(tmp, buf, sizeof(tmp)), "/", p ? p+1 : nil);
 			if(!nobody)
 				n = snprint(buf, sizeof(buf), 
 				"<html><head><title>%s</title></head>\n"
@@ -570,23 +608,21 @@
 int
 block(void)
 {
-	char *r;
-	Pair *h;
+	int a;
 
 	if(nelem(blockagents) > 0){
-		h = findhdr(nil, "User-Agent");
-		if(h){
-			r = blockagent(h->val);
-			if(r){
-				syslog(0, "tcp80", "BLOCK User-Agent:'%s' %s", h->val, r);
-				return 1;
-			}
+		a = blockagent(useragent);
+		if(a){
+			if(a & Log)
+				syslog(0, "tcp80", "BLOCK '%s'", useragent);
+			return 1;
 		}
 	}
 	if(nelem(blockrules) > 0){
-		r = blockrule(location);
-		if(r){
-			syslog(0, "tcp80", "BLOCK %s %s", location, r);
+		a = blockrule(location);
+		if(a){
+			if(a & Log)
+				syslog(0, "tcp80", "BLOCK '%s'", location);
 			return 1;
 		}
 	}
@@ -597,24 +633,22 @@
 box(void)
 {
 	char *r;
-	Pair *h;
 
 	if(bind("/sys/log/tcp80", "/usr/web/sys/log/tcp80", MREPL) < 0)
 		return 0;
-	if(nelem(hostrules) > 0){
-		h = findhdr(nil, "Host");
-		if (h){
-			r = hostrule(h->val);
-			if(r){
-				if(bind(r, "/mnt/web", MREPL) < 0)
-					return 0;
-				if(bind("/mnt/web", "/usr/web", MBEFORE) < 0)
-					return 0;
-			}
+	if(bind("/env/timezone", "/usr/web/env/timezone", MREPL) < 0)
+		return 0;
+	if(bind("/dev/sysname", "/usr/web/dev/sysname", MREPL) < 0)
+		return 0;
+	if(nelem(hosts) > 0){
+		r = findhost(host);
+		if(r){
+			if(bind(r, "/mnt/web", MREPL) < 0)
+				return 0;
+			if(bind("/mnt/web", "/usr/web", MBEFORE) < 0)
+				return 0;
 		}
 	}
-	if(addns("none", "/lib/namespace.httpd") < 0)
-		return 0;
 	if(bind("/usr/web", "/", MREPL) < 0)
 		return 0;
 	if(rfork(RFNOMNT) < 0)
@@ -659,7 +693,8 @@
 			if(*buf != ' ' && *buf != '\t' && *line){
 				if(lineno++ == 0){
 					nstrcpy(method, token(line, "\t ", &s), sizeof(method));
-					nstrcpy(location, token(s, "\t ", nil), sizeof(location));
+					nstrcpy(location, token(s, "\t ", &s), sizeof(location));
+					nstrcpy(proto, token(s, "\t ", nil), sizeof(proto));
 				} else {
 					if(lineno > 100)
 						return;
@@ -671,11 +706,7 @@
 						h = aheader + naheader++;
 						nstrcpy(h->key, k, sizeof(h->key));
 						nstrcpy(h->val, x, sizeof(h->val));
-						if(x = strchr(h->val, ';')){
-							*x++ = 0;
-							x = token(x, ";", nil);
-						}
-						h->att = x;
+						savehdr(h);
 						h->next = header;
 						header = h;
 					}
@@ -701,8 +732,12 @@
 				if(h == nil)
 					return;
 				method[0] = 0;
+				proto[0] = 0;
 				naheader = 0;
 				header = nil;
+				host = nil;
+				referer = nil;
+				useragent = nil;
 				lineno = 0;
 			}
 		}