Make some last minute production changes

This commit is contained in:
Justine Tunney 2022-10-19 10:00:29 -07:00
parent f7ff77d865
commit 69bee64a59
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
8 changed files with 166 additions and 61 deletions

View file

@ -1,31 +1,49 @@
-- reverse proxy for turfwar
ProgramPort(443)
ProgramTokenBucket()
if IsDaemon() then
ProgramPort(443)
ProgramUid(65534)
ProgramUid(65534)
ProgramLogPath('/var/log/turfbean.log')
ProgramPidPath('/var/log/turfbean.pid')
ProgramTrustedIp(ParseIp(Slurp('/etc/justine-ip.txt')), 32);
ProgramCertificate(Slurp('/etc/letsencrypt/live/ipv4.games-ecdsa/fullchain.pem'))
ProgramPrivateKey(Slurp('/etc/letsencrypt/live/ipv4.games-ecdsa/privkey.pem'))
end
RELAY_HEADERS_TO_CLIENT = {
'Access-Control-Allow-Origin',
'Cache-Control',
'Connection',
'Content-Encoding',
'Content-Type',
'Last-Modified',
'Referrer-Policy',
'Vary',
}
function OnServerStart()
ProgramTokenBucket()
assert(unix.setrlimit(unix.RLIMIT_NPROC, 1000, 1000))
end
function OnWorkerStart()
assert(unix.setrlimit(unix.RLIMIT_RSS, 2*1024*1024))
assert(unix.setrlimit(unix.RLIMIT_CPU, 2))
assert(unix.unveil(nil, nil))
assert(unix.pledge("stdio inet", nil, unix.PLEDGE_PENALTY_RETURN_EPERM))
end
function OnHttpRequest()
local url = 'http://127.0.0.1' .. EscapePath(GetPath())
local name = GetParam('name')
if name then
url = url .. '?name=' .. EscapeParam(name)
end
local status, headers, body =
Fetch('http://127.0.0.1' .. EscapePath(GetPath()),
Fetch(url,
{method = GetMethod(),
headers = {
['Accept'] = GetHeader('Accept'),
['Accept-Encoding'] = GetHeader('Accept-Encoding'),
['CF-IPCountry'] = GetHeader('CF-IPCountry'),
['If-Modified-Since'] = GetHeader('If-Modified-Since'),
['Referer'] = GetHeader('Referer'),
@ -39,7 +57,7 @@ function OnHttpRequest()
end
Write(body)
else
err = headers
local err = headers
Log(kLogError, "proxy failed %s" % {err})
ServeError(503)
end

View file

@ -37,18 +37,11 @@ int main(int argc, char *argv[]) {
}
int fd;
struct sockaddr_un addr = {
AF_UNIX,
"/var/run/blackhole.sock",
};
struct sockaddr_un addr = {AF_UNIX, "/var/run/blackhole.sock"};
if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
kprintf("error: socket(AF_UNIX) failed: %s\n", strerror(errno));
return 3;
}
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
kprintf("error: connect(%#s) failed: %s\n", addr.sun_path, strerror(errno));
return 4;
}
int rc = 0;
for (int i = 1; i < argc; ++i) {
@ -56,8 +49,9 @@ int main(int argc, char *argv[]) {
char buf[4];
if ((ip = ParseIp(argv[i], -1)) != -1) {
WRITE32BE(buf, ip);
if (write(fd, buf, 4) == -1) {
kprintf("error: write() failed: %s\n", strerror(errno));
if (sendto(fd, buf, 4, 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
kprintf("error: sendto(%#s) failed: %s\n", addr.sun_path,
strerror(errno));
rc |= 2;
}
} else {

View file

@ -45,6 +45,7 @@
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/timer.h"
#include "libc/time/struct/tm.h"
#include "net/http/http.h"
#include "third_party/getopt/getopt.h"
#include "third_party/musl/passwd.h"
@ -55,12 +56,13 @@
#define DEFAULT_LOGNAME "/var/log/blackhole.log"
#define DEFAULT_PIDNAME "/var/run/blackhole.pid"
#define DEFAULT_SOCKNAME "/var/run/blackhole.sock"
#define GETOPTS "L:S:P:M:G:dh"
#define GETOPTS "L:S:P:M:G:W:dh"
#define USAGE \
"\
Usage: blackholed [-hdLPSMG]\n\
Usage: blackholed [-hdLPSMGW]\n\
-h help\n\
-d daemonize\n\
-W IP whitelist ip address\n\
-L PATH log file name (default: " DEFAULT_LOGNAME ")\n\
-P PATH pid file name (default: " DEFAULT_PIDNAME ")\n\
-S PATH socket file name (default: " DEFAULT_SOCKNAME ")\n\
@ -131,6 +133,7 @@ const char *g_sockname;
const char *g_iptables;
sig_atomic_t g_shutdown;
struct SortedInts g_blocked;
struct SortedInts g_whitelisted;
static wontreturn void ShowUsage(int fd, int rc) {
write(fd, USAGE, sizeof(USAGE) - 1);
@ -139,8 +142,23 @@ static wontreturn void ShowUsage(int fd, int rc) {
_Exit(rc);
}
static void GetOpts(int argc, char *argv[]) {
char *GetTimestamp(void) {
struct timespec ts;
static struct tm tm;
static int64_t last;
static char str[27];
clock_gettime(0, &ts);
if (ts.tv_sec != last) {
localtime_r(&ts.tv_sec, &tm);
last = ts.tv_sec;
}
iso8601us(str, &tm, ts.tv_nsec);
return str;
}
void GetOpts(int argc, char *argv[]) {
int opt;
int64_t ip;
g_sockmode = 0777;
g_pidname = DEFAULT_PIDNAME;
g_logname = DEFAULT_LOGNAME;
@ -165,6 +183,16 @@ static void GetOpts(int argc, char *argv[]) {
case 'M':
g_sockmode = strtol(optarg, 0, 8) & 0777;
break;
case 'W':
if ((ip = ParseIp(optarg, -1)) != -1) {
if (InsertInt(&g_whitelisted, ip, true)) {
LOG("whitelisted %s", optarg);
}
} else {
kprintf("error: could not parse -W %#s IP address\n", optarg);
_Exit(1);
}
break;
case 'h':
ShowUsage(1, 0);
default:
@ -173,20 +201,6 @@ static void GetOpts(int argc, char *argv[]) {
}
}
char *GetTimestamp(void) {
struct timespec ts;
static struct tm tm;
static int64_t last;
static char str[27];
clock_gettime(0, &ts);
if (ts.tv_sec != last) {
localtime_r(&ts.tv_sec, &tm);
last = ts.tv_sec;
}
iso8601us(str, &tm, ts.tv_nsec);
return str;
}
void OnTerm(int sig) {
char tmp[15];
LOG("got %s", strsignal_r(sig, tmp));
@ -278,9 +292,11 @@ void Daemonize(void) {
}
void UseLog(void) {
_npassert(dup2(g_logfd, 2) == 2);
if (g_logfd != 2) {
_npassert(!close(g_logfd));
if (g_logfd > 0) {
_npassert(dup2(g_logfd, 2) == 2);
if (g_logfd != 2) {
_npassert(!close(g_logfd));
}
}
}
@ -426,6 +442,7 @@ int main(int argc, char *argv[]) {
if ((ip = READ32BE(msg))) {
if (IsMyIp(ip) || // nics
ContainsInt(&g_whitelisted, ip) || // protected
(ip & 0xff000000) == 0x00000000 || // 0.0.0.0/8
(ip & 0xff000000) == 0x7f000000) { // 127.0.0.0/8
LOG("won't block %s", FormatIp(ip));

View file

@ -1,5 +0,0 @@
#!/bin/sh
make -j16 o//net/turfwar/blackholed.elf &&
sudo chown root o//net/turfwar/blackholed.elf &&
sudo chmod 06755 o//net/turfwar/blackholed.elf &&
exec o//net/turfwar/blackholed.elf

View file

@ -39,6 +39,7 @@
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/mem/sortedints.internal.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/paths.h"
#include "libc/runtime/internal.h"
@ -118,13 +119,14 @@
#define TB_BYTES (1u << TB_CIDR)
#define TB_WORDS (TB_BYTES / 8)
#define GETOPTS "idvp:w:k:"
#define GETOPTS "idvp:w:k:W:"
#define USAGE \
"\
Usage: turfwar.com [-dv] ARGS...\n\
-i integrity check and vacuum at startup\n\
-d daemonize\n\
-v verbosity\n\
-W IP whitelist\n\
-p INT port\n\
-w INT workers\n\
-k INT keepalive\n\
@ -247,6 +249,7 @@ bool g_daemonize;
int g_port = PORT;
int g_workers = WORKERS;
int g_keepalive = KEEPALIVE_MS;
struct SortedInts g_whitelisted;
// lifecycle vars
pthread_t g_listener;
@ -417,7 +420,7 @@ bool Blackhole(uint32_t ip) {
sizeof(g_blackhole.addr)) == 4) {
return true;
} else {
kprintf("error: sendto(/var/run/blackhole.sock) failed: %s\n",
kprintf("error: sendto(%#s) failed: %s\n", g_blackhole.addr.sun_path,
strerror(errno));
return false;
}
@ -891,7 +894,8 @@ void *HttpWorker(void *arg) {
ksnprintf(ipbuf, sizeof(ipbuf), "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16,
ip >> 8, ip);
if (!ipv6 && (tok = AcquireToken(g_tok.b, ip, TB_CIDR)) < 32) {
if (!ipv6 && !ContainsInt(&g_whitelisted, ip) &&
(tok = AcquireToken(g_tok.b, ip, TB_CIDR)) < 32) {
if (tok > 4) {
LOG("%s rate limiting client\n", ipbuf, msg->version);
Write(client.sock, "HTTP/1.1 429 Too Many Requests\r\n"
@ -1342,8 +1346,9 @@ void OnCtrlC(int sig) {
}
// parses cli arguments
static void GetOpts(int argc, char *argv[]) {
void GetOpts(int argc, char *argv[]) {
int opt;
int64_t ip;
while ((opt = getopt(argc, argv, GETOPTS)) != -1) {
switch (opt) {
case 'i':
@ -1364,6 +1369,16 @@ static void GetOpts(int argc, char *argv[]) {
case 'v':
++__log_level;
break;
case 'W':
if ((ip = ParseIp(optarg, -1)) != -1) {
if (InsertInt(&g_whitelisted, ip, true)) {
LOG("whitelisted %s", optarg);
}
} else {
kprintf("error: could not parse -w %#s IP address\n", optarg);
_Exit(1);
}
break;
case '?':
write(1, USAGE, sizeof(USAGE) - 1);
exit(0);