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;
}
}