Compare commits

..

44 Commits

Author SHA1 Message Date
d320b3319d Bump versions 2024-11-05 17:35:51 +01:00
9c22642a4b Reduce default instance number and add server sizing recommendation - Fixes #140 2024-10-18 11:29:10 +02:00
708e0a798b Update mysql path 2024-09-22 10:15:46 +02:00
f66f8faba4 Bump versions 2024-09-21 22:21:36 +02:00
85fc40ac85 Bump versions 2024-08-31 13:10:21 +02:00
6c20f5fb3a Move chroot creation to jailkit 2024-08-31 13:10:02 +02:00
9039e5b282 Bump version 2024-08-18 13:47:07 +02:00
c8ff688804 Merge pull request #138 from DEAM0/patch-2
Update README.md
2024-08-03 18:50:28 +02:00
08de8bfbca Update README.md 2024-08-03 16:09:02 +02:00
0c673483c8 Make use of deb.sury.org nginx 2024-07-28 19:21:34 +02:00
2dac5be589 SVN no longer in use 2024-07-13 12:01:20 +02:00
9201440a23 Update rspamd config file locations 2024-07-12 17:23:34 +02:00
9952f570a2 Make use of system rspamd 2024-07-12 17:19:09 +02:00
40294a5f16 Bump version 2024-07-07 16:17:47 +02:00
d3dea7493e Bump versions 2024-07-07 11:31:37 +02:00
00e88c28cb Bump versions 2024-06-11 17:23:15 +02:00
a537c1951c Bump versions 2024-06-02 14:39:03 +02:00
6b3131ba72 Bump versions 2024-04-11 12:41:27 +02:00
7ce9c8b2df Bump versions 2024-03-03 04:10:49 +01:00
26d7641476 Bump versions 2024-02-12 18:53:24 +01:00
da164f0214 Enable more imagemagick formats 2024-02-07 19:14:30 +01:00
04ac6b3f64 Bump versions 2024-01-26 17:47:23 +01:00
b95e94520d Bump versions 2024-01-20 14:12:20 +01:00
d9854af2fc Bump versions 2023-12-25 17:02:15 +01:00
5a0aefffc1 Bump versions and replace luajit with repository version 2023-12-16 19:06:57 +01:00
13a7cb8a46 Add captcha difficulty hard 2023-12-10 10:14:45 +01:00
212cb17038 Remove unneeded patch 2023-12-10 09:55:00 +01:00
2a38afe72d Bump versions 2023-12-08 20:49:08 +01:00
1a574acc92 Enable hyperscan 2023-11-15 20:31:28 +01:00
996db7f3fe Bump versions 2023-11-14 19:14:05 +01:00
613fb66bc3 Add new translations 2023-10-27 10:14:02 +02:00
bec7028304 Bump versions 2023-10-27 10:10:39 +02:00
5db791499a Update translation
Co-authored-by: Анонім <g2014test@yandex.com>
Translate-URL: https://weblate.danwin1210.de/projects/DanWin/hosting/uk/
Translation: DanWin/Hosting
2023-10-14 20:51:42 +00:00
efa31d7ffa Update translation
Co-authored-by: Анонім <g2014test@yandex.com>
2023-10-13 18:42:29 +00:00
31249c6c97 Merge pull request #133 from DEAM0/patch-1
Update install_binaries.sh
2023-10-10 13:56:01 +02:00
47011b6f1c Update install_binaries.sh 2023-10-10 13:52:47 +02:00
a6e25edaf8 Bump version 2023-10-10 08:39:09 +02:00
649137e5f4 Add php8.3 to build script 2023-10-09 13:19:11 +02:00
dd89208bdd Bump versions 2023-10-08 10:26:40 +02:00
7a3b4963c8 Bump versions 2023-10-07 16:08:26 +02:00
1a82182187 Enable Onion Service Proof of Work defense 2023-09-05 21:15:43 +02:00
d3d1cc5d4f Add video tutorial link 2023-09-03 11:02:02 +02:00
aca4e19980 Drop v2 onion support 2023-08-24 23:05:12 +02:00
3c30c5b370 simplify quota initialization 2023-08-24 22:54:38 +02:00
38 changed files with 1499 additions and 1703 deletions

View File

@ -2,6 +2,7 @@ General Information:
--------------------
This is a setup for a Tor based shared hosting server. It is provided as is and before putting it into production you should make changes according to your needs. This is a work in progress and you should carefully check the commit history for changes before updating.
For a production server, at least 1TB of SSD disk space, 32GB RAM and 8 CPU cores is recommended. For a small testing/personal server, 4GB RAM and 1 CPU core is enough.
Translation:
--------------------------
@ -14,11 +15,13 @@ Once you are done, you can open a pull request, or [email me](mailto:daniel@danw
Installation Instructions:
--------------------------
The configuration was tested with a standard Debian bullseye and Ubuntu 20.04 LTS installation. It's recommended you install Debian bullseye (or newer) on your server, but with a little tweaking you may also get this working on other distributions and/or versions. If you want to build it on a raspberry pi, please do not use the raspbian images as several things will break. Download an image for your pi model from [https://raspi.debian.net/daily-images/](https://raspi.debian.net/daily-images/) instead.
The configuration was tested with a standard Debian bookworm and Ubuntu 24.04 LTS installation. It's recommended you install Debian bookworm (or newer) on your server, but with a little tweaking you may also get this working on other distributions and/or versions. If you want to build it on a raspberry pi, please do not use the raspbian images as several things will break. Download an image for your pi model from [https://raspi.debian.net/daily-images/](https://raspi.debian.net/daily-images/) instead.
Because I regularly get asked to make a video tutorial on how to set this up, I decided to create a tutorial which you can [watch on YouTube](https://www.youtube.com/watch?v=f2-SOlnIYmg). It is basically just copy-pasting commands, but maybe it helps someone.
Uninstall packages that may interfere with this setup:
```
DEBIAN_FRONTEND=noninteractive apt-get purge -y apache2* dnsmasq* eatmydata exim4* imagemagick-6-common mysql-client* mysql-server* nginx* libnginx-mod* php7* resolvconf && systemctl disable systemd-resolved.service && systemctl stop systemd-resolved.service
DEBIAN_FRONTEND=noninteractive apt purge -y apache2* dnsmasq* eatmydata exim4* imagemagick-6-common mysql-client* mysql-server* nginx* libnginx-mod* php7* resolvconf && systemctl disable systemd-resolved.service && systemctl stop systemd-resolved.service
```
If you have problems resolving hostnames after this step, temporarily switch to a public nameserver like 1.1.1.1 (from CloudFlare) or 8.8.8.8 (from Google)
@ -27,10 +30,20 @@ If you have problems resolving hostnames after this step, temporarily switch to
rm /etc/resolv.conf && echo "nameserver 1.1.1.1" > /etc/resolv.conf
```
Add additional repositories:
```
apt update && apt install git apt-transport-tor curl
curl -sSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc > /etc/apt/trusted.gpg.d/torproject.gpg
curl -sSL https://packages.sury.org/nginx/apt.gpg > /etc/apt/trusted.gpg.d/sury.gpg
echo "deb tor://apow7mjfryruh65chtdydfmqfpj5btws7nbocgtaovhvezgccyjazpqd.onion/torproject.org/ `lsb_release -cs` main" >> /etc/apt/sources.list
echo "deb https://packages.sury.org/nginx/ `lsb_release -cs` main" >> /etc/apt/sources.list
apt update && apt upgrade
```
Install git and clone this repository
```
apt-get update && apt-get install git && git clone https://github.com/DanWin/hosting && cd hosting
apt update && apt install git && git clone https://github.com/DanWin/hosting && cd hosting
```
Install custom optimized binaries
@ -38,21 +51,12 @@ Install custom optimized binaries
./install_binaries.sh
```
To get the latest mariadb version, you should follow these instructions to add the official repository for your distribution: (https://downloads.mariadb.org/mariadb/repositories/)
Add torproject to our repositories:
```
curl --socks5-hostname 127.0.0.1:9050 -sSL http://apow7mjfryruh65chtdydfmqfpj5btws7nbocgtaovhvezgccyjazpqd.onion/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc > /etc/apt/trusted.gpg.d/torproject.gpg
echo "deb tor://apow7mjfryruh65chtdydfmqfpj5btws7nbocgtaovhvezgccyjazpqd.onion/torproject.org/ `lsb_release -cs` main" >> /etc/apt/sources.list
apt-get update && apt-get upgrade
```
Note that debian also has an onion service package archive, so you may want to edit /etc/apt/sources.list to load from there instead:
```
deb tor://2s4yqjx5ul6okpp3f2gaunr2syex5jgbfpfvhxxbbjwnrsvbk5v3qbid.onion/debian `lsb_release -cs` main
```
Copy (and modify according to your needs) the site files in `var/www` to `/var/www`, `usr/local` to `/usr/local` and the configuration files in `etc` to `/etc` after installation has finished. Then restart some services:
Copy (and modify according to your needs) the site files in `var/www` to `/var/www` and the configuration files in `etc` to `/etc` after installation has finished. Then restart some services:
```
systemctl daemon-reload && systemctl restart bind9.service && systemctl restart tor@default.service
```
@ -98,12 +102,12 @@ To harden the system and hide pids from non-root users, also add the following:
proc /proc proc defaults,hidepid=2 0 0
```
And add the `noatime,usrjquota=aquota.user,jqfmt=vfsv1` options to the `/home` mountpoint (if not a separate partition, the `/` mointpoint and `noatime`to `/`. Then initialize quota (replace `/home` with `/`, if you do not have a separate partition):
And add the `noatime,usrjquota=aquota.user,jqfmt=vfsv1` options to the `/home` mountpoint, then initialize quota. Replace `/home` with `/`, if you do not have a separate partition:
```
systemctl daemon-reload
mount -o remount /home
quotacheck -cMu /home
quotaon /home
mount -o remount $(findmnt -n -o TARGET --target /home)
quotacheck -cMu $(findmnt -n -o TARGET --target /home)
quotaon $(findmnt -n -o TARGET --target /home)
```
In some cases, you might get an error, that quota is not supported. This is usually the case in virtual environments. Make sure you have the full kernel installed, not one with a `-virtual` package. They usually are `linux-image-amd64`, `linux-image-arm64` or `linux-image-generic`, depending on your distribution. Also make sure, you are running a real virtual machine (e.g. KVM). Some providers sell containerized VPSes (e.g. OpenVZ), which means you don't run your own kernel...

View File

@ -1,3 +1,3 @@
#!/bin/sh
# Run this script whenever nginx doesn't start up due to stale sockets
rm -f /home/*/var/run/mysqld/mysqld.sock /home/*/var/run/mail.sock /run/nginx.sock /run/nginx/* /var/www/var/run/mysqld/mysqld.sock /var/www/var/run/mail.sock /var/spool/postfix/var/run/mysqld/mysqld.sock
rm -f /home/*/run/mysqld/mysqld.sock /home/*/run/mail.sock /run/nginx.sock /run/nginx/* /var/www/run/mysqld/mysqld.sock /var/www/run/mail.sock /var/spool/postfix/var/run/mysqld/mysqld.sock

175
etc/jailkit/jk_init.ini Normal file
View File

@ -0,0 +1,175 @@
[uidbasics]
# this section probably needs adjustment on 64bit systems
# or non-Linux systems
comment = common files for all jails that need user/group information
paths = /lib/libnsl.so.*, /lib64/libnsl.so.*, /lib/libnss*.so.2, /lib64/libnss*.so.2, /lib/i386-linux-gnu/libnsl.so.*, /lib/i386-linux-gnu/libnss*.so.2, /lib/x86_64-linux-gnu/libnsl.so.*, /lib/x86_64-linux-gnu/libnss*.so.2, /lib/arm-linux-gnueabihf/libnss*.so.2, /lib/arm-linux-gnueabihf/libnsl*.so.*, /etc/nsswitch.conf, /etc/ld.so.conf
# Solaris needs
# paths = /etc/default/nss, /lib/libnsl.so.1, /usr/lib/nss_*.so.1, /etc/nsswitch.conf
[netbasics]
comment = common files for all jails that need any internet connectivity
paths = /lib/libnss_dns.so.2, /lib64/libnss_dns.so.2, /lib/libnss_mdns*.so.2, /etc/resolv.conf, /etc/host.conf, /etc/hosts, /etc/protocols, /etc/services
# on Solaris devices /dev/udp and /dev/tcp might be needed too, not sure
[logbasics]
comment = timezone information and log sockets
paths = /etc/localtime
need_logsocket = 1
# Solaris does not need logsocket
# but needs
# devices = /dev/log, /dev/conslog
[jk_lsh]
comment = Jailkit limited shell
paths = /usr/sbin/jk_lsh, /etc/jailkit/jk_lsh.ini
users = root
groups = root
includesections = uidbasics, logbasics
[limitedshell]
comment = alias for jk_lsh
includesections = jk_lsh
[cvs]
comment = Concurrent Versions System
paths = cvs
devices = /dev/null
[git]
comment = Fast Version Control System
paths = /usr/bin/git*, /usr/lib/git-core, /usr/share/git-core, /usr/bin/basename, /bin/uname, /usr/bin/pager
includesections = editors, perl
[scp]
comment = ssh secure copy
paths = scp
includesections = netbasics, uidbasics
devices = /dev/urandom, /dev/null
[sftp]
comment = ssh secure ftp
paths = /usr/lib/sftp-server, /usr/libexec/openssh/sftp-server, /usr/lib/misc/sftp-server, /usr/libexec/sftp-server, /usr/lib/openssh/sftp-server
includesections = netbasics, uidbasics
devices = /dev/urandom, /dev/null
# on solaris
#paths = /usr/lib/ssh/sftp-server
[ssh]
comment = ssh secure shell
paths = ssh
includesections = netbasics, uidbasics
devices = /dev/urandom, /dev/tty, /dev/null
[rsync]
paths = rsync
includesections = netbasics, uidbasics
[procmail]
comment = procmail mail delivery
paths = procmail, /bin/sh
devices = /dev/null
[basicshell]
comment = bash based shell with several basic utilities
paths = /bin/sh, bash, ls, cat, chmod, mkdir, cp, cpio, date, dd, echo, egrep, false, fgrep, grep, gunzip, gzip, ln, ls, mkdir, mktemp, more, mv, pwd, rm, rmdir, sed, sh, sleep, sync, tar, touch, true, uncompress, zcat, /etc/motd, /etc/issue, /etc/bash.bashrc, /etc/bashrc, /etc/profile, /usr/lib/locale/en_US.utf8
users = root
groups = root
includesections = uidbasics
[interactiveshell]
comment = for ssh access to a full shell
includesections = uidbasics, basicshell, terminfo, editors, extendedshell
[midnightcommander]
comment = Midnight Commander
paths = mc, mcedit, mcview, /usr/share/mc
includesections = basicshell, terminfo
[extendedshell]
comment = bash shell including things like awk, bzip, tail, less
paths = awk, bzip2, bunzip2, ldd, less, clear, cut, du, find, head, less, md5sum, nice, sort, tac, tail, tr, sort, wc, watch, whoami
includesections = basicshell, midnightcommander, editors
[terminfo]
comment = terminfo databases, required for example for ncurses or vim
paths = /etc/terminfo, /usr/share/terminfo, /lib/terminfo
[editors]
comment = vim, joe and nano
includesections = terminfo
paths = joe, nano, vi, vim, /etc/vimrc, /etc/joe, /usr/share/vim
[netutils]
comment = several internet utilities like wget, ftp, rsync, scp, ssh
paths = wget, lynx, ftp, host, rsync, smbclient
includesections = netbasics, ssh, sftp, scp
[apacheutils]
comment = htpasswd utility
paths = htpasswd
[extshellplusnet]
comment = alias for extendedshell + netutils + apacheutils
includesections = extendedshell, netutils, apacheutils
[openvpn]
comment = jail for the openvpn daemon
paths = /usr/sbin/openvpn
users = root,nobody
groups = root,nogroup
#includesections = netbasics
devices = /dev/urandom, /dev/random, /dev/net/tun
includesections = netbasics, uidbasics
need_logsocket = 1
[apache]
comment = the apache webserver, very basic setup, probably too limited for you
paths = /usr/sbin/apache
users = root, www-data
groups = root, www-data
includesections = netbasics, uidbasics
[perl]
comment = the perl interpreter and libraries
paths = perl, /usr/lib/perl, /usr/lib/perl5, /usr/share/perl, /usr/share/perl5
[xauth]
comment = getting X authentication to work
paths = /usr/bin/X11/xauth, /usr/X11R6/lib/X11/rgb.txt, /etc/ld.so.conf
[xclients]
comment = minimal files for X clients
paths = /usr/X11R6/lib/X11/rgb.txt
includesections = xauth
[vncserver]
comment = the VNC server program
paths = Xvnc, Xrealvnc, /usr/X11R6/lib/X11/fonts/
includesections = xclients
[ping]
comment = Ping program
paths_w_setuid = /bin/ping
#[xterm]
#comment = xterm
#paths = /usr/bin/X11/xterm, /usr/share/terminfo, /etc/terminfo
#devices = /dev/pts/0, /dev/pts/1, /dev/pts/2, /dev/pts/3, /dev/pts/4, /dev/ptyb4, /dev/ptya4, /dev/tty, /dev/tty0, /dev/tty4
[php]
comment = the php interpreter and libraries
paths = /usr/bin/php*, composer, /usr/bin/phar*, env, /usr/lib/php, /usr/share/php, /usr/share/php*, /usr/share/zoneinfo, /usr/share/ca-certificates, /etc/ssl/certs, /usr/lib/ssl/certs, /etc/localtime
includesections = netbasics
[locales]
comment = all translations
paths = /usr/lib/locale, /usr/share/i18n, /etc/default/locale, /etc/locale.alias
[custom_hosting]
comment = custom giftGRÜN configuration
includesections = php, git, netutils, interactiveshell, locales
devices = /dev/zero, /dev/random
paths = base32, base64, basenc, brotli, cksum, comm, csplit, curl, dirname, dir, expand, expr, factor, fmt, fold, gpg, id, install, join, link, mysql, mysqldump, mysqlcheck, nl, nohup, numfmt, od, openssl, paste, pr, printenv, printf, ptx, readlink, realpath, seq, sha1sum, sha224sum, sha256sum, sha384sum, sha512sum, shred, shuf, split, stat, stdbuf, sum, test, tee, timeout, tput, truncate, tsort, unexpand, uniq, unlink, unxz, unzip, vdir, which, xargs, xz, zip, zopfli, nologin, /etc/bash_completion, /etc/bash_completion.d, /usr/share/bash-completion, /etc/profile.d, /etc/ld.so.conf.d, /etc/hostname
emptydirs = /run/mysqld, /tmp
users = root, www-data
groups = root, www-data

View File

@ -11,7 +11,6 @@ innodb_buffer_pool_size = 1G
innodb_log_buffer_size = 16M
innodb_log_file_size = 128M
innodb_flush_log_at_trx_commit = 2
#innodb-defragment = 1
skip_name_resolve = 1
query_cache_size = 128M
query_cache_limit = 4M

View File

@ -2,6 +2,7 @@ daemon on;
user www-data;
worker_processes 1;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
pcre_jit on;
worker_rlimit_nofile 100000;
worker_shutdown_timeout 30m;

View File

@ -23,7 +23,7 @@ ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#allow tor traffic
for tor in bind debian-tor _tor-a _tor-b _tor-c _tor-d _tor-e _tor-f _tor-g _tor-h _tor-i _tor-j _tor-k _tor-l _tor-m _tor-n _tor-o _tor-p _tor-q _tor-r _tor-s; do(
for tor in bind debian-tor _tor-a; do(
iptables -t nat -A OUTPUT -m owner --uid-owner $tor -j RETURN
ip6tables -t nat -A OUTPUT -m owner --uid-owner $tor -j RETURN
iptables -A OUTPUT -m owner --uid-owner $tor -j ACCEPT

View File

@ -24,7 +24,7 @@ LockPersonality=true
SystemCallArchitectures=native
ReadWritePaths=-/var/log/nginx/
ReadWritePaths=-/var/lib/nginx/
ReadWritePaths=-/var/www/var/run/
ReadWritePaths=-/var/www/run/
ReadWritePaths=-/var/spool/postfix/
ReadWritePaths=-/run/
InaccessiblePaths=-/root/

View File

@ -1,17 +0,0 @@
[Unit]
Description=rapid spam filtering system
After=nss-lookup.target network-online.target
Documentation=https://rspamd.com/doc/
[Service]
LimitNOFILE=1048576
NonBlocking=true
ExecStart=/usr/local/bin/rspamd -c /usr/local/etc/rspamd/rspamd.conf -f
ExecReload=/bin/kill -HUP $MAINPID
User=_rspamd
RuntimeDirectory=rspamd
RuntimeDirectoryMode=0755
Restart=always
[Install]
WantedBy=multi-user.target

View File

@ -13,6 +13,7 @@ HiddenServiceEnableIntroDoSRatePerSec 10
HiddenServiceEnableIntroDoSBurstPerSec 100
HiddenServiceMaxStreams 10
HiddenServiceMaxStreamsCloseCircuit 1
HiddenServicePoWDefensesEnabled 1
ClientUseIPv6 1
ClientUseIPv4 1

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@ const DBUSER='hosting'; // Database user
const DBPASS='MY_PASSWORD'; // Database password
const DBNAME='hosting'; // Database
const PERSISTENT=true; // Use persistent database conection true/false
const DBVERSION=20; //database layout version
const CAPTCHA=1; // Captcha difficulty (0=off, 1=simple, 2=moderate, 3=extreme)
const DBVERSION=21; //database layout version
const CAPTCHA=1; // Captcha difficulty (0=off, 1=simple, 2=moderate, 3=hard, 4=extreme)
const ADDRESS='dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion'; // our own address
const CANONICAL_URL='https://hosting.danwin1210.me'; // our preferred domain for search engines
const SERVERS=[ //servers and ports we are running on
@ -25,7 +25,7 @@ const INDEX_MD5S=[ //MD5 sums of index.hosting.html files that should be conside
const REQUIRE_APPROVAL=false; //require admin approval of new sites? true/false
const ENABLE_SHELL_ACCESS=true; //allows users to login via ssh, when disabled only sftp is allowed - run setup.php to migrate existing accounts
const ADMIN_PASSWORD='MY_PASSWORD'; //password for admin interface
const SERVICE_INSTANCES=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's']; //one character per instance - run multiple tor+php-fpm instances for load balancing, remove all but one instance if you expect less than 200 accounts. If tor starts using 100% cpu and failing circuits every few hours after a restart, add more instances. In my experience this happens around 250 hidden services per instance - run setup.php after change
const SERVICE_INSTANCES=['a']; //one character per instance - run multiple tor+php-fpm instances for load balancing, remove all but one instance if you expect less than 200 accounts. If tor starts using 100% cpu and failing circuits every few hours after a restart, add more instances. In my experience this happens around 250 hidden services per instance - run setup.php after change
const DISABLED_PHP_VERSIONS=[]; //php versions still installed on the system but no longer offered for new accounts
const PHP_VERSIONS=[7 => '8.1', 8 => '8.2']; //currently active php versions
const DEFAULT_PHP_VERSION='8.2'; //default php version
@ -95,6 +95,8 @@ const CLEARNET_ADDRESS = 'hosting.danwin1210.me'; //Domain under which the servi
const CLEARNET_SUBDOMAINS = 'danwin1210.me'; //domain of which all subdomains are mapped to this server
const DEFAULT_LANG = 'en'; //default language
const LANGUAGES = [ //available languages
'cs' => ['name' => 'Czech', 'locale' => 'cs_CZ', 'dir' => 'ltr'],
'de' => ['name' => 'Deutsch', 'locale' => 'de_DE', 'dir' => 'ltr'],
'en' => ['name' => 'English', 'locale' => 'en_GB', 'dir' => 'ltr'],
];
@ -139,14 +141,6 @@ bindtextdomain('hosting', __DIR__.'/locale');
bind_textdomain_codeset('hosting', 'UTF-8');
textdomain('hosting');
function get_onion_v2($pkey) : string {
$keyData = openssl_pkey_get_details($pkey);
$pk = base64_decode(substr($keyData['key'], 27, -26));
$skipped_first_22 = substr($pk, 22);
$first_80_bits_of_sha1 = hex2bin(substr(sha1($skipped_first_22), 0, 20));
return base32_encode($first_80_bits_of_sha1);
}
function get_onion_v3(string $sk) : string {
if(PHP_INT_SIZE === 4){
$pk = ParagonIE_Sodium_Core32_Ed25519::sk_to_pk($sk);
@ -223,6 +217,45 @@ function send_captcha(): void
imagesetpixel($im, mt_rand(0, 55), mt_rand(0, 24), $dots);
}
echo '<img width="55" height="24" src="data:image/gif;base64,';
}elseif(CAPTCHA === 3){
$im = imagecreatetruecolor(55, 24);
$bg = imagecolorallocatealpha($im, 0, 0, 0, 127);
$fg = imagecolorallocate($im, 255, 255, 255);
$cc = imagecolorallocate($im, 200, 200, 200);
$cb = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $bg);
$line = imagecolorallocate($im, 255, 255, 255);
$deg = (mt_rand(0,1)*2-1)*mt_rand(10, 20);
$background = imagecreatetruecolor(120, 80);
imagefill($background, 0, 0, $cb);
for ($i=0; $i<20; ++$i) {
$char=imagecreatetruecolor(12, 16);
imagestring($char, 5, 2, 2, $captchachars[mt_rand(0, $length)], $cc);
$char = imagerotate($char, (mt_rand(0,1)*2-1)*mt_rand(10, 20), $cb);
$char = imagescale($char, 24, 32);
imagefilter($char, IMG_FILTER_SMOOTH, 0.6);
imagecopy($background, $char, rand(0, 100), rand(0, 60), 0, 0, 24, 32);
}
imagestring($im, 5, 5, 5, $code, $fg);
$im = imagescale($im, 110, 48);
imagefilter($im, IMG_FILTER_SMOOTH, 0.5);
imagefilter($im, IMG_FILTER_GAUSSIAN_BLUR);
$im = imagerotate($im, $deg, $bg);
$im = imagecrop($im, array('x'=>0, 'y'=>0, 'width'=>120, 'height'=>80));
imagecopy($background, $im, 0, 0, 0, 0, 110, 80);
imagedestroy($im);
$im = $background;
for($i=0;$i<1000;++$i){
$c = mt_rand(100,230);
$dots=imagecolorallocate($im, $c, $c, $c);
imagesetpixel($im, mt_rand(0, 120), mt_rand(0, 80), $dots);
}
imagedestroy($char);
echo '<img width="120" height="80" src="data:image/png;base64,';
}else{
$im = imagecreatetruecolor(150, 200);
$bg = imagecolorallocate($im, 0, 0, 0);
@ -403,6 +436,7 @@ HiddenServiceExportCircuitID haproxy
HiddenServiceEnableIntroDoSDefense 1
HiddenServiceEnableIntroDoSRatePerSec 10
HiddenServiceEnableIntroDoSBurstPerSec 100
HiddenServicePoWDefensesEnabled 1
";
$torrc.="HiddenServicePort 80 unix:/var/run/nginx/$socket\n";
if($tmp['enable_smtp']){
@ -420,47 +454,7 @@ function private_key_to_onion(string $priv_key) : array {
$onion = '';
$priv_key = trim($priv_key);
$version = 0;
if(($pkey = openssl_pkey_get_private($priv_key)) !== false){
$version = 2;
$details = openssl_pkey_get_details($pkey);
if($details['type'] === OPENSSL_KEYTYPE_RSA){
$p = gmp_init(bin2hex($details['rsa']['p']), 16);
$q = gmp_init(bin2hex($details['rsa']['q']), 16);
$n = gmp_init(bin2hex($details['rsa']['n']), 16);
$d = gmp_init(bin2hex($details['rsa']['d']), 16);
$dmp1 = gmp_init(bin2hex($details['rsa']['dmp1']), 16);
$dmq1 = gmp_init(bin2hex($details['rsa']['dmq1']), 16);
$iqmp = gmp_init(bin2hex($details['rsa']['iqmp']), 16);
}
if($details['type'] !== OPENSSL_KEYTYPE_RSA){
$message = 'Error: private key is not an RSA key.';
$ok = false;
}elseif($details['bits'] !== 1024){
$message = 'Error: private key not of bitsize 1024.';
$ok = false;
}elseif(gmp_prob_prime($p) === 0){
$message = 'Error: p is not a prime';
$ok = false;
}elseif(gmp_prob_prime($q) === 0){
$message = 'Error: q is not a prime';
$ok = false;
}elseif(gmp_cmp($n, gmp_mul($p, $q) ) !== 0){
$message = 'Error: n does not equal p q';
$ok = false;
}elseif(gmp_cmp($dmp1, gmp_mod($d, gmp_sub($p, 1) ) ) !==0 ){
$message = 'Error: dmp1 invalid';
$ok = false;
}elseif(gmp_cmp($dmq1, gmp_mod($d, gmp_sub($q, 1) ) ) !== 0){
$message = 'Error: dmq1 invalid';
$ok = false;
}elseif(gmp_cmp($iqmp, gmp_invert($q, $p) ) !==0 ){
$message = 'Error: iqmp not inverse of q';
$ok = false;
}else{
$onion = get_onion_v2($pkey);
}
return ['ok' => $ok, 'message' => $message, 'onion' => $onion, 'version' => $version];
} elseif(($priv = base64_decode($priv_key, true)) !== false){
if(($priv = base64_decode($priv_key, true)) !== false){
$version = 3;
if( ! str_starts_with( $priv, '== ed25519v1-secret: type0 ==' . hex2bin( '000000' ) ) || strlen($priv) !== 96){
$message = 'Error: v3 secret key invalid.';
@ -478,11 +472,7 @@ function private_key_to_onion(string $priv_key) : array {
function generate_new_onion(int $version = 3) : array {
$priv_key = '';
$onion = '';
if($version === 2){
$pkey = openssl_pkey_new(['private_key_bits' => 1024, 'private_key_type' => OPENSSL_KEYTYPE_RSA]);
openssl_pkey_export($pkey, $priv_key);
$onion = get_onion_v2($pkey);
} else {
if($version === 3){
$seed = random_bytes(32);
$sk = ed25519_seckey_expand($seed);
$priv_key = base64_encode('== ed25519v1-secret: type0 ==' . hex2bin('000000') . $sk);
@ -610,12 +600,12 @@ function rewrite_nginx_config(): void
continue;
}
$nginx_mysql.="server {
listen unix:/home/$tmp[system_account]/var/run/mysqld/mysqld.sock;
listen unix:/home/$tmp[system_account]/run/mysqld/mysqld.sock;
proxy_pass unix:/var/run/mysqld/mysqld.sock;
}
";
$nginx_mail.="server {
listen unix:/home/$tmp[system_account]/var/run/mail.sock;
listen unix:/home/$tmp[system_account]/run/mail.sock;
root /var/www/mail;
location / {
include snippets/fastcgi-php.conf;

View File

@ -68,7 +68,7 @@ if(isset($_POST['action']) && $_POST['action']==='add_onion'){
}
}else{
$onion_version = 3;
if(isset($_REQUEST['onion_type']) && in_array($_REQUEST['onion_type'], [2, 3])){
if(isset($_REQUEST['onion_type']) && in_array($_REQUEST['onion_type'], [3])){
$onion_version = $_REQUEST['onion_type'];
}
$check=$db->prepare('SELECT null FROM onions WHERE onion=?;');
@ -210,9 +210,6 @@ if($count_onions<MAX_NUM_USER_ONIONS){
echo '<label><input type="radio" name="onion_type" value="3"';
echo (!isset($_POST['onion_type']) || $_POST['onion_type']==3) ? ' checked' : '';
echo '>'._('Random v3 Address').'</label>';
echo '<label><input type="radio" name="onion_type" value="2"';
echo isset($_POST['onion_type']) && $_POST['onion_type']==2 ? ' checked' : '';
echo '>'._('Random v2 Address').'</label>';
echo '<label><input id="custom_onion" type="radio" name="onion_type" value="custom"';
echo isset($_POST['onion_type']) && $_POST['onion_type']==='custom' ? ' checked' : '';
echo '>'._('Custom private key');

View File

@ -74,7 +74,7 @@ if($_SERVER['REQUEST_METHOD']==='POST'){
}
}
}else{
if(isset($_REQUEST['onion_type']) && in_array($_REQUEST['onion_type'], [2, 3])){
if(isset($_REQUEST['onion_type']) && in_array($_REQUEST['onion_type'], [3])){
$onion_version = $_REQUEST['onion_type'];
}
$check=$db->prepare('SELECT null FROM onions WHERE onion=?;');
@ -148,7 +148,6 @@ foreach(PHP_VERSIONS as $key => $version){
<tr><td colspan=2><label><input type="checkbox" name="autoindex" value="1"<?php echo $autoindex; ?>><?php echo _('Enable autoindex (listing of files)'); ?></label></td></tr>
<tr><td colspan=2><?php echo _('Type of hidden service:'); ?><br>
<label><input type="radio" name="onion_type" value="3"<?php echo (!isset($_POST['onion_type']) || $_POST['onion_type']==3) ? ' checked' : ''; ?>><?php echo _('Random v3 Address'); ?></label>
<label><input type="radio" name="onion_type" value="2"<?php echo isset($_POST['onion_type']) && $_POST['onion_type']==2 ? ' checked' : ''; ?>><?php echo _('Random v2 Address'); ?></label>
<label><input id="custom_onion" type="radio" name="onion_type" value="custom"<?php echo isset($_POST['onion_type']) && $_POST['onion_type']==='custom' ? ' checked' : ''; ?>><?php echo _('Custom private key'); ?>
<textarea id="private_key" name="private_key" rows="5" cols="28">
<?php echo isset($_REQUEST['private_key']) ? htmlspecialchars($_REQUEST['private_key']) : ''; ?>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -156,6 +156,9 @@ if(!$version){
if($version<20){
$db->exec("ALTER TABLE onions CHANGE max_streams max_streams tinyint(3) unsigned NOT NULL DEFAULT '6';");
}
if($version<21){
$db->exec('UPDATE onions SET enabled=-1 WHERE version = 2;');
}
$stmt=$db->prepare("UPDATE settings SET value=? WHERE setting='version';");
$stmt->execute([DBVERSION]);
}
@ -361,7 +364,7 @@ if(!file_exists("/etc/nginx/streams-enabled/")){
mkdir("/etc/nginx/streams-enabled/", 0755, true);
}
file_put_contents('/etc/nginx/streams-enabled/default', "server {
listen unix:/var/www/var/run/mysqld/mysqld.sock;
listen unix:/var/www/run/mysqld/mysqld.sock;
proxy_pass unix:/var/run/mysqld/mysqld.sock;
}");
exec('systemctl enable nginx');

View File

@ -1,334 +1,33 @@
#!/bin/bash
set -e
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
test "$1" != "" || { echo "Need path to chroot directory"; exit 1; }
ALL_LIB_DIRECTORIES=()
ALL_LIB_FILES=()
### functions
function CHROOT_BINARY() {
BINARY="$(which $1)"
if [ "$BINARY" == "" ]; then
return;
fi
if [ "$(echo $BINARY | grep -E '.*:.*')" != "" ]; then
BINARY="$(echo $BINARY | cut -d':' -f2)"
fi
LIB_FILES="$(ldd $BINARY 2>&1 | grep -v 'not a dynamic executable' | awk '{ print $3 }' | grep -E '^/(.*)' || echo)"
LDD_FILES="$(ldd $BINARY 2>&1 | grep -v 'not a dynamic executable' | grep 'ld-linux' | awk '{ print $1; }' || echo)"
if [ "$LIB_FILES" != "" ]; then
for LIB_FILE in $LIB_FILES; do
ADD_LIB $LIB_FILE
done
fi
if [ "$LDD_FILES" != "" ]; then
for LDD_FILE in $LDD_FILES; do
ADD_LIB $LDD_FILE
done
fi
BINARY_DIRECTORY="$(dirname $BINARY)"
mkdir -pm 0555 $CHROOT_DIRECTORY$BINARY_DIRECTORY
cp $BINARY $CHROOT_DIRECTORY$BINARY
chmod 0555 $CHROOT_DIRECTORY$BINARY
}
function ADD_LIB() {
LIB_DIRECTORY="$(dirname $1)"
if [[ ! "${ALL_LIB_DIRECTORIES[@]}" =~ "$LIB_DIRECTORY" ]]; then
ALL_LIB_DIRECTORIES=(${ALL_LIB_DIRECTORIES[@]} "$LIB_DIRECTORY")
fi
if [[ ! "${ALL_LIB_FILES[@]}" =~ "$1" ]]; then
ALL_LIB_FILES=(${ALL_LIB_FILES[@]} "$1")
fi
}
function CHROOT_LIBRARIES() {
for DIRECTORY in ${ALL_LIB_DIRECTORIES[@]}; do
mkdir -pm 0555 $CHROOT_DIRECTORY$DIRECTORY
done
for FILE in ${ALL_LIB_FILES[@]}; do
cp $FILE $CHROOT_DIRECTORY$FILE
chmod 0555 $CHROOT_DIRECTORY$FILE
done
}
### variables
CHROOT_DIRECTORY=$1
CHROOT_DIRECTORY_STRUCTURE=(
'/etc'
'/etc/default'
'/dev'
'/tmp'
'/usr'
'/usr/share'
'/usr/share/bash-completion'
'/usr/share/bash-completion/completions'
'/usr/bin'
'/usr/lib'
'/usr/lib/openssh'
'/usr/sbin'
'/var'
'/var/run'
'/var/run/mysqld'
)
CHROOT_DIRECTORY_TO_CLEAN=(
'/bin'
'/lib'
'/usr/bin'
'/usr/lib'
'/usr/sbin'
)
BINARIES_GENERAL=(
'['
'awk'
'base32'
'base64'
'basename'
'basenc'
'bash'
'brotli'
'bzip2'
'cat'
'chmod'
'cksum'
'clear'
'comm'
'composer'
'cp'
'csplit'
'curl'
'cut'
'date'
'dd'
'dirname'
'dir'
'du'
'echo'
'egrep'
'env'
'expand'
'expr'
'factor'
'false'
'fgrep'
'find'
'fmt'
'fold'
'git'
'git-receive-pack'
'git-shell'
'git-upload-archive'
'git-upload-pack'
'gpg'
'grep'
'gunzip'
'gzip'
'head'
'id'
'install'
'join'
'less'
'link'
'ln'
'ls'
'md5sum'
'mkdir'
'mktemp'
'mv'
'mysql'
'mysqldump'
'mysqlcheck'
'nano'
'nl'
'nohup'
'numfmt'
'od'
'openssl'
'paste'
'php8.1'
'php8.2'
'pr'
'printenv'
'printf'
'ptx'
'pwd'
'readlink'
'realpath'
'rm'
'rmdir'
'rsync'
'scp'
'sed'
'seq'
'sftp'
'sh'
'sha1sum'
'sha224sum'
'sha256sum'
'sha384sum'
'sha512sum'
'shred'
'shuf'
'sleep'
'sort'
'split'
'ssh'
'stat'
'stdbuf'
'sum'
'tac'
'tail'
'tar'
'test'
'tee'
'timeout'
'touch'
'tput'
'tr'
'true'
'truncate'
'tsort'
'uname'
'unexpand'
'uniq'
'unlink'
'unxz'
'unzip'
'vdir'
'vi'
'vim'
'wc'
'wget'
'which'
'xargs'
'xz'
'zip'
'zopfli'
'nologin'
)
FILES_GENERAL=(
'/etc/hosts'
'/etc/hostname'
'/etc/resolv.conf'
'/etc/nsswitch.conf'
'/etc/services'
'/etc/protocols'
'/etc/locale.alias'
'/etc/default/locale'
'/etc/localtime'
'/etc/profile'
'/etc/bash_completion'
'/etc/bash.bashrc'
'/usr/share/bash-completion/bash_completion'
'/usr/share/bash-completion/completions/alias'
'/usr/share/bash-completion/completions/bind'
'/usr/share/bash-completion/completions/bzip2'
'/usr/share/bash-completion/completions/compgen'
'/usr/share/bash-completion/completions/complete'
'/usr/share/bash-completion/completions/curl'
'/usr/share/bash-completion/completions/declare'
'/usr/share/bash-completion/completions/export'
'/usr/share/bash-completion/completions/find'
'/usr/share/bash-completion/completions/function'
'/usr/share/bash-completion/completions/git'
'/usr/share/bash-completion/completions/gzip'
'/usr/share/bash-completion/completions/id'
'/usr/share/bash-completion/completions/kill'
'/usr/share/bash-completion/completions/mysql'
'/usr/share/bash-completion/completions/openssl'
'/usr/share/bash-completion/completions/pwd'
'/usr/share/bash-completion/completions/rsync'
'/usr/share/bash-completion/completions/scp'
'/usr/share/bash-completion/completions/sh'
'/usr/share/bash-completion/completions/sftp'
'/usr/share/bash-completion/completions/tar'
'/usr/share/bash-completion/completions/typeset'
'/usr/share/bash-completion/completions/wget'
'/etc/ld.so.conf'
)
DIRECTORIES_GENERAL=(
'/usr/lib/git-core'
'/usr/share/git-core'
'/usr/lib/locale'
'/usr/share/i18n'
'/etc/ssl'
'/usr/lib/ssl'
'/usr/share/ca-certificates'
'/etc/bash_completion.d'
'/usr/share/zoneinfo'
'/lib/terminfo'
'/usr/share/terminfo'
'/usr/lib/php'
'/etc/profile.d'
'/etc/ld.so.conf.d'
)
### test variables/parameters
test "$CHROOT_DIRECTORY" != ""
if [ "$2" != "" ]; then
CHROOT_BINARY $2
CHROOT_LIBRARIES
ldconfig -r $CHROOT_DIRECTORY
jk_cp -j "$CHROOT_DIRECTORY" -k "$2"
echo "copied extra binary $2";
exit 0;
fi
### init chroot directory
mkdir -p $CHROOT_DIRECTORY
chown root:www-data $CHROOT_DIRECTORY
chmod 550 $CHROOT_DIRECTORY
for DIRECTORY in ${CHROOT_DIRECTORY_TO_CLEAN[@]}; do
rm -rf $CHROOT_DIRECTORY$DIRECTORY
done
ln -s usr/bin $CHROOT_DIRECTORY/bin
ln -s usr/lib $CHROOT_DIRECTORY/lib
for DIRECTORY in ${CHROOT_DIRECTORY_STRUCTURE[@]}; do
mkdir -pm 0555 $CHROOT_DIRECTORY$DIRECTORY
done
chmod 777 $CHROOT_DIRECTORY/tmp
# users and groups
echo "root:x:0:0:root:/root:/bin/bash" > $CHROOT_DIRECTORY/etc/passwd
echo "www-data:x:33:33::/var/www:/bin/bash" >> $CHROOT_DIRECTORY/etc/passwd
echo "root:x:0:" > $CHROOT_DIRECTORY/etc/group
echo "www-data:x:33:www-data" >> $CHROOT_DIRECTORY/etc/group
# /dev devices
test -e $CHROOT_DIRECTORY/dev/null || mknod -m 666 $CHROOT_DIRECTORY/dev/null c 1 3
test -e $CHROOT_DIRECTORY/dev/zero || mknod -m 666 $CHROOT_DIRECTORY/dev/zero c 1 5
test -e $CHROOT_DIRECTORY/dev/tty || mknod -m 666 $CHROOT_DIRECTORY/dev/tty c 5 0
test -e $CHROOT_DIRECTORY/dev/random || mknod -m 644 $CHROOT_DIRECTORY/dev/random c 1 8
test -e $CHROOT_DIRECTORY/dev/urandom || mknod -m 644 $CHROOT_DIRECTORY/dev/urandom c 1 9
# copy general directories
for DIRECTORY in ${DIRECTORIES_GENERAL[@]}; do
rm -rf $CHROOT_DIRECTORY$DIRECTORY
cp -Rp $DIRECTORY $CHROOT_DIRECTORY$DIRECTORY
done
echo "export HOME=/" > $CHROOT_DIRECTORY/etc/profile.d/hosting.sh
echo "export HISTFILE=/.bash_history" >> $CHROOT_DIRECTORY/etc/profile.d/hosting.sh
echo 'export PATH="$PATH:/.composer/vendor/bin"' >> $CHROOT_DIRECTORY/etc/profile.d/hosting.sh
# copy general files
for FILE in ${FILES_GENERAL[@]}; do
cp $FILE $CHROOT_DIRECTORY$FILE
done
### copy shared libraries and binaries
# general
for BINARY in ${BINARIES_GENERAL[@]}; do
CHROOT_BINARY $BINARY
done
# git
for BINARY in `find /usr/lib/git-core -type f`; do
CHROOT_BINARY $BINARY
done
# networking
for LIB in /lib/*/libnss_*; do
ADD_LIB $LIB
done
# php
for LIB in /usr/lib/php/*/*.so; do
ADD_LIB $LIB
done
CHROOT_LIBRARIES
ldconfig -r $CHROOT_DIRECTORY
ln -f $CHROOT_DIRECTORY/usr/bin/php8.2 $CHROOT_DIRECTORY/usr/bin/php
if [[ -d "$CHROOT_DIRECTORY/bin" ]]; then
chown root:root "$CHROOT_DIRECTORY"
chmod 555 "$CHROOT_DIRECTORY"
jk_update -j "$CHROOT_DIRECTORY" -k /bin /lib /usr
else
mkdir -p "$CHROOT_DIRECTORY"
chown root:root "$CHROOT_DIRECTORY"
chmod 555 "$CHROOT_DIRECTORY"
jk_init -j "$CHROOT_DIRECTORY" -k custom_hosting
chmod 777 "$CHROOT_DIRECTORY/tmp"
echo "export HOME=/" > "$CHROOT_DIRECTORY/etc/profile.d/hosting.sh"
echo "export HISTFILE=/.bash_history" >> "$CHROOT_DIRECTORY/etc/profile.d/hosting.sh"
echo 'export PATH="$PATH:/.composer/vendor/bin"' >> "$CHROOT_DIRECTORY/etc/profile.d/hosting.sh"
fi