Compare commits

...

12 commits

Author SHA1 Message Date
0f29851a37 Ready for 2.6.0 people 2025-02-23 18:25:42 +01:00
77819962cc I don't know why I haven't done this before.
- Added variables for instance information and contact
- Added favicon
2025-02-23 16:25:52 +01:00
838d9da904 Damn. For some reason the improved logging thing decided to nuke itself 2025-02-23 14:24:55 +01:00
99868f3fe7 fixed installation 2025-02-23 14:04:49 +01:00
ec299f915f updated the docs 2025-02-23 13:59:40 +01:00
47065f1c07 Added rc script for freebsd 2025-02-22 14:02:36 +01:00
dd26aa599e last try 2025-02-21 03:11:55 +01:00
74a654ea5c test 2025-02-21 03:06:50 +01:00
b7f0e62177 AIs are RETARDE 2025-02-21 03:01:54 +01:00
9c0fcc3528 Let's try this lol 2025-02-21 03:00:03 +01:00
6d16b0a97d Of course I had to do something bad 2025-02-21 02:53:48 +01:00
b40f3e7001 FINALLY fixed the logging thing and also logs to STDOUT
Got the client's actual IP address by using X-Forwarded-For header,
because some reverse proxy software (i.e. haproxy, relayd) will
override the IP address as the reverse proxy is the actual client.

Fixes #26
2025-02-21 02:52:01 +01:00
10 changed files with 249 additions and 118 deletions

37
.github/workflows/sakisafe_http.yml vendored Normal file
View file

@ -0,0 +1,37 @@
# This was written by an AI. HA!
# I hate writing yaml. I'm glad a computer can do it for me.
name: Test Mojolicious Application
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
web:
image: perl:latest
ports:
- 8080:8080
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y libmojolicious-perl liblist-moreutils-perl libmojolicious-plugin-renderfile-perl libpath-tiny-perl libmime-types-perl
- name: Start Sakisafe
run: |
hypnotoad http/sakisafe.pl
- name: Test Sakisafe
run: |
curl --retry 10 --retry-delay 5 --retry-connrefused http://localhost:8080
# LOLOLOLOLOLOLOLO
curl -X POST -F "file=@/etc/passwd" http://localhost:8080
- name: Read log entry
run: |
cat http/sakisafe.log

View file

@ -1,4 +1,4 @@
Copyright $CURRENT_YEAR qorg11.
Copyright $CURRENT_YEAR SURAGU Enterprises
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View file

@ -7,6 +7,13 @@
* Written in perl
* Can be used as pastebin
* Easy installation (just a simple daemon and use a reverse proxy)
* Does not bully Tor users ;)
# Installation
sakisafe is written in Perl, so it is its first dependency. But if you're
using a real operating system you should have it by default.
1. install the dependencies using `cpan`:
@ -14,6 +21,16 @@
cpan -i Mojolicious::Lite Mojolicious::Routes::Pattern Mojoliciuos::Plugin::RenderFile
~~~
If you're running Debian or FreeBSD you can install the dependencies with
your package manager:
~~~bash
apt install libmojolicious-perl libmojolicious-plugin-renderfile-perl liblist-moreutils-perl # Debian, Ubuntu...
pkg install p5-Mojolicious p5-List-MoreUtils p5-Path-Tiny # FreeBSD
# You'll have to run cpan to install the RenderFile plugin in FreeBSD
cpan -Ti Mojolicious::Plugin::Renderfile
~~~
2. Clone the repo and start the daemon:
~~~
@ -21,6 +38,31 @@ git clone https://git.suragu.net/sosa/sakisafe
cd sakisafe/http
./sakisafe.pl daemon -m production
~~~
You can also use `hypnotoad` or `morbo` to run the thing:
~~~
morbo -l http://*:3000 sakisafe.pl.
hypnotoad sakisafe.pl # This will daemonize the thing in port 8080.
~~~
2.2. In FreeBSD, you can use the rc script located in
http/scripts/sakisafe_bsd to create a sakisafe service. The service is
loaded by the user "saki", whose home is `/usr/local/share/sakisafe`:
~~~bash
mkdir -p /usr/local/share/sakisafe
cp -r http/* /usr/local/share/sakisafe
cp http/init/sakisafe_bsd /usr/local/etc/rc.d
touch /var/run/sakisafe.pid
chmod 777 /var/run/sakisafe.pid # How to fix this? Please tell me
service sakisafe enable
service sakisafe start
~~~
Please contribute more init scripts for sakisafe!!! (for systemd,
openbsd...)
2.3. You can also use Docker. I am not a Docker advocate. But apparently
running "docker build-x" or something like that just works.
3. Create a 'f' directory in the directory sakisafe will run with
`mkdir f`. Make sure that the user which will run sakisafe.pl can
@ -42,8 +84,8 @@ server {
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
proxy_set_header X-Real-IP $remote_addr; # Important for logging!
proxy_set_header X-Forwarded-for $remote_addr; # Idem
proxy_pass http://127.0.0.1:3000$request_uri;
}
}
@ -64,6 +106,7 @@ other file upload services). It also supports file uploading via scp
* Highly configurable
* Lightweight
* If using OpenBSD, it will run `pledge()` for security reasons.
* As far as I know, runs in any *NIX operating system.
## Installation
@ -83,6 +126,9 @@ Use `bmake` instead of `make`, and you'll also need these deps:
![](https://repology.org/badge/vertical-allrepos/sakisafe.svg)
TODO: Add the thing to Debian repositories ;)
# Contributing
Just create a pull request in GitHub or send a diff file.

View file

@ -1,10 +1,9 @@
* Known lainsafe instances
* Known sakisafe instances
In this document i'll add all the lainsafe instance i know :)
In this document i'll add all the sakisafe instance i know :)
- https://lainsafe.delegao.moe
- https://lainsafe.duckdns.org (don't use it, old lainsafe version
and a bit incompatible with lainsafecli)
- https://lainsafe.kalli.st
- http://lainsafe.kallist4mcluuxbjnr5p2asdlmdhaos3pcrvhk3fbzmiiiftwg6zncid.onion/ (onion mirror)
- http://gnaumuq27fagoo24pb2mmf25rdic7lrthq2fsfolgrpzycc2hwga.b32.i2p/
Feel free to add more. I do not know about many others.
- https://ss.suragu.net
- https://files.getimiskon.xyuz
-

View file

@ -1,17 +0,0 @@
name: C/C++ CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: bmake
run: bmake

1
http/hypnotoad.pid Normal file
View file

@ -0,0 +1 @@
16143

24
http/init/sakisafe_bsd Normal file
View file

@ -0,0 +1,24 @@
#
# Add the following lines to /etc/rc.conf to enable sakisafe:
#
#sakisafe_enable="YES"
. /etc/rc.subr
name="sakisafe"
rcvar="sakisafe_enable"
load_rc_config $name
: ${sakisafe_user:=saki}
: ${sakisafe_group:=saki}
: ${sakisafe_enable:=NO}
: ${sakisafe_flags:= -P /var/run/sakisafe.pid -f /usr/local/bin/morbo -l http://*:3000 /usr/local/share/sakisafe/sakisafe.pl }
: ${sakisafe_chdir:= /usr/local/share/sakisafe }
command="/usr/sbin/daemon"
command_args="${sakisafe_flags}"
pidfile="/var/run/${name}.pid"
PATH="${PATH}"
run_rc_command "$1"

BIN
http/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -1,4 +1,4 @@
p {
p, ul, li {
color: white;
display: block;
}
@ -24,7 +24,8 @@ body {
}
h1, h2 {
color: #e3e3e3;
color: #e3e3e3;
font-family: monospace;
}
.left {
position: absolute;

View file

@ -1,9 +1,11 @@
#!/usr/bin/perl
#!/usr/bin/env perl
# This file is part of sakisafe.
use if $^O eq "openbsd", OpenBSD::Pledge, qw(pledge);
use Mojolicious::Lite -signatures;
use Mojolicious::Routes::Pattern;
use Mojo::Log;
use Time::HiRes;
use List::MoreUtils qw(uniq);
use Carp;
use Term::ANSIColor;
@ -19,118 +21,144 @@ plugin 'RenderFile';
pledge("stdio prot_exec cpath rpath wpath inet flock fattr")
if $^O eq "openbsd";
# 500 MBs
# INSTANCE CONFIGURATION
our $name = "sakisafe";
our $version = "2.6.0";
# Domain and port, for output link
our $domain = "XXXXXXXXXXX";
our $port = 443;
# Contact info
# Change this with whatever you want
our $contact_info = 'email: saki@sakisafe.lol';
# 1 GiBs
my $MAX_SIZE = 1024 * 1024 * 1000;
my @BANNED = eval { path('banned.txt')->slurp_utf8 }
or qw(); # Add banned IP addresses here
or qw(); # Add banned IP addresses here
my @BANNED_EXTS = eval { path('banned_exts.txt')->slurp_utf8 }
or qw(); # Add forbidden files extensions here
or qw(); # Add forbidden files extensions here
my $dirname;
my $link;
mkdir "f";
# Mojo logger
my $log = Mojo::Log->new(path => 'sakisafe.log', level => 'trace');
$log->color(1);
# Forward logs to STDERR or STDOUT while also writing to the `sakisafe.log` file.
$log->on(message => sub ($l, $level, @lines) {
my $time = time;
my ($s, $m, $h, $day, $month, $year) = localtime time;
$time = sprintf('%04d-%02d-%02d %02d:%02d:%08.5f', $year + 1900, $month + 1, $day, $h, $m,
"$s." . ((split '.', $time)[1] // 0));
my $log_to_print = '[' . $time . '] ' . '[' . $level . '] ' . join(' ', @lines);
if ($level eq 'trace' || $level eq 'info') {
say $log_to_print;
} else {
print \*STDERR, $log_to_print . "\n";
}
}
);
# Function to handle file uploads
sub logger ( $level, $address, $message ) {
open( my $fh, ">>", "sakisafe.log" );
printf( $fh "[%s]: %s has uploaded file %s\n", $level, $address, $message );
close($fh);
}
sub handle_file {
my $c = shift;
my $filedata = $c->param("file");
if ( $filedata->size > $MAX_SIZE ) {
return $c->render(
text => "Max upload size: $MAX_SIZE",
status => 400
);
}
my $c = shift;
my $filedata = $c->param("file");
if ( $filedata->size > $MAX_SIZE ) {
return $c->render(
text => "Max upload size: $MAX_SIZE",
status => 400
);
}
if ( List::MoreUtils::any { /$c->tx->remote_address/ } uniq @BANNED ) {
$c->render(
text =>
"Hi! Seems like the server admin added your IP address to the banned IP array."
. "As the developer of sakisafe, I can't do anything.",
status => 403
);
return;
}
if ( List::MoreUtils::any { /$c->req->headers->header('X-Forwarded-For')/ } uniq @BANNED ) {
$c->render(
text =>
"Hi! Seems like the server admin added your IP address to the banned IP array."
. "As the developer of sakisafe, I can't do anything.",
status => 403
);
return;
}
# Generate random string for the directory
my @chars = ( '0' .. '9', 'a' .. 'Z' );
$dirname .= $chars[ rand @chars ] for 1 .. 5;
my $filename = $filedata->filename;
my ($ext) = $filename =~ /(\.[^.]+)$/;
if ( List::MoreUtils::any { /$ext/ } uniq @BANNED_EXTS ) {
$c->render( text => "You cannot this filetype.\n", status => 415 );
say $ext;
logger( "WARN", $c->tx->remote_address, $dirname . "/" . $filename );
return;
}
carp( color("bold yellow"),
"sakisafe warning: could not create directory: $ERRNO",
color("reset") )
unless mkdir( "f/" . $dirname );
$filename .= ".txt" if $filename eq "-";
# Generate random string for the directory
my @chars = ( '0' .. '9', 'a' .. 'Z' );
$dirname .= $chars[ rand @chars ] for 1 .. 5;
my $filename = $filedata->filename;
my ($ext) = $filename =~ /(\.[^.]+)$/;
if ( List::MoreUtils::any { /$ext/ } uniq @BANNED_EXTS ) {
$c->render( text => "You cannot this filetype.\n", status => 415 );
$log->info("Attempt to upload by banned extension: " . $c->req->headers->header('X-Forwarded-For'));
say $ext;
return;
}
$c->req->headers->header('X-Forwarded-For')
unless mkdir( "f/" . $dirname );
# TODO: get whether the server is http or https
# There's a CGI ENV variable for that.
my $host = $c->req->url->to_abs->host;
my $ua = $c->req->headers->user_agent;
$filedata->move_to( "f/" . $dirname . "/" . $filename );
$link = "http://$host/f/$dirname/$filename";
$c->stash( link => $link, host => $host, dirname => $dirname );
$filename .= ".txt" if $filename eq "-";
$c->res->headers->header( 'Location' => "$link" . $filename );
# TODO: get whether the server is http or https
# There's a CGI ENV variable for that.
my $host = $c->req->url->to_abs->host;
my $ua = $c->req->headers->user_agent;
$filedata->move_to( "f/" . $dirname . "/" . $filename );
$link = "http://$host/f/$dirname/$filename";
$c->stash( link => $link, host => $host, dirname => $dirname );
# Only give the link to curl, html template for others.
$c->res->headers->header( 'Location' => "$link" . $filename );
if ( $ua =~ m/curl/ || $ua eq "" ) {
$c->render(
text => $link . "\n",
status => 201,
);
# Only give the link to curl, html template for others.
$dirname = "";
}
else {
$c->render(
template => 'file',
status => 201,
);
}
logger( "INFO", $c->tx->remote_address, $dirname . "/" . $filename );
if ( $ua =~ m/curl/ || $ua eq "" ) {
$c->render(
text => $link . "\n",
status => 201,
);
$dirname = "";
} else {
$c->render(
template => 'file',
status => 201,
);
}
$log->info($c->req->headers->header('X-Forwarded-For') . " " . $dirname . "/" . $filename );
$dirname = "";
}
# Function to log uploaded files
get '/' => 'index';
get '/' => sub ($c) {
$c->stash(name => $name, contact_info => $contact_info, version => $version);
$c->render(template => 'index');
};
post '/' => sub ($c) { handle_file($c) };
# Allow files to be downloaded.
get '/f/:dir/#name' => sub ($c) {
my $dir = $c->param("dir");
my $file = $c->param("name");
my $ext = $file;
$ext =~ s/.*\.//;
my $path = "f/" . $dir . "/" . $file;
#carp "sakisafe warning: could not get file: $ERRNO" unless
$c->render( text => "file not found", status => 404 ) unless -e $path;
$c->render_file(
filepath => $path,
format => $ext,
content_disposition => 'inline'
);
};
my $dir = $c->param("dir");
my $file = $c->param("name");
my $ext = $file;
$ext =~ s/.*\.//;
my $path = "f/" . $dir . "/" . $file;
#carp "sakisafe warning: could not get file: $ERRNO" unless
$c->render( text => "file not found", status => 404 ) unless -e $path;
$c->render_file(
filepath => $path,
format => $ext,
content_disposition => 'inline'
);
}
;
app->log($log);
app->max_request_size( 1024 * 1024 * 100 );
post '/upload' => sub ($c) { handle_file($c) };
@ -147,6 +175,7 @@ app->start;
# to get the template here. So a TODO is to fix this.
__DATA__
@@ file.html.ep
<!DOCTYPE html>
<html lang="en">
@ -163,15 +192,14 @@ __DATA__
<h2>LINK</h2>
<code><%= $link %></code>
</center>
<p>Running sakisafe 2.4.0</p>
<p>Running sakisafe 2.6.0</p>
</body>
</html>
__END__
@@ index.html.ep
<!DOCTYPE html>
% layout 'index', name => $name, contact_info => $contact_info, version => $version;
<!DOCTYPE html>
<html lang="en">
<head>
<title>sakisafe</title>
@ -190,7 +218,19 @@ __DATA__
<code>curl -F 'file=@-' https://<%= $c->req->url->to_abs->host; %></code><br/>
<a href="https://git.suragu.net/svragv/sakisafe">Git repository</a>
</center>
<p>Running sakisafe 2.4.0</p>
<h2>FAQ</h2>
<p>(No one has ever asked these questions)</p>
<p><b>How long are the files stored?</b> Until the heat death of the universe</b></p>
<p><b>Do you log IP addresses?</b> Yes. Blame the people uploading illegal stuff to this</p>
<p><b>Do you log all the requests?</b> Nah. Only file uploads are logged.</p>
<p><b>Can you delete a file I uploaded?</b><p>That depends on the instance administrator</b></p>
<h2>Instance info</h2>
<ul>
<li>Name: <%= $name %></li>
<li>Contact info: <%= $contact_info%>
</ul>
<p>Running sakisafe <%=$version%></p>
<div class="left">
<h2>Or just upload a file here</h2>
<form ENCTYPE='multipart/form-data' method='post' action='/upload'>