Compare commits

...

2 Commits

Author SHA1 Message Date
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
6 changed files with 13 additions and 66 deletions

View File

@ -98,12 +98,12 @@ To harden the system and hide pids from non-root users, also add the following:
proc /proc proc defaults,hidepid=2 0 0 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 systemctl daemon-reload
mount -o remount /home mount -o remount $(findmnt -n -o TARGET --target /home)
quotacheck -cMu /home quotacheck -cMu $(findmnt -n -o TARGET --target /home)
quotaon /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... 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

@ -6,7 +6,7 @@ export LANG=C.UTF-8
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin" export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
# install all required packages # install all required packages
DEBIAN_FRONTEND=noninteractive apt-get update DEBIAN_FRONTEND=noninteractive apt-get update
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y apt-transport-tor bash-completion bind9 brotli bzip2 ca-certificates clamav-daemon clamav-freshclam curl dovecot-imapd dovecot-lmtpd dovecot-pop3d git hardlink haveged iptables libio-socket-ip-perl libsasl2-modules locales locales-all logrotate lsb-release mariadb-server nano postfix postfix-mysql quota quotatool redis rsync ssh subversion tor unzip vim wget xz-utils zip zopfli DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y apt-transport-tor bash-completion bind9 brotli bzip2 ca-certificates clamav-daemon clamav-freshclam curl dovecot-imapd dovecot-lmtpd dovecot-pop3d git hardlink haveged iptables libio-socket-ip-perl libsasl2-modules locales locales-all logrotate lsb-release mariadb-server nano postfix postfix-mysql quota quotatool redis rsync ssh subversion tor unzip util-linux vim wget xz-utils zip zopfli
# build dependencies # build dependencies
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y autoconf automake bison cmake g++ gcc ghostscript gnupg libaom-dev `apt-cache search --names-only 'libargon2(-0)?-dev' | awk '{print $1;}' | head -n1` libbrotli-dev libbz2-dev libc-client2007e-dev libcurl4-openssl-dev libde265-dev libdjvulibre-dev libedit-dev `apt-cache search --names-only 'libenchant(-2)?-dev' | awk '{print $1;}' | head -n1` libffi-dev `apt-cache search --names-only libfreetype6?-dev | awk '{print $1;}' | head -n1` libfftw3-dev libfribidi-dev libgd-dev libgmp-dev libgpg-error-dev libgpgme-dev libharfbuzz-dev libheif-dev libkrb5-dev libldap2-dev liblmdb-dev liblqr-1-0-dev libmariadb-dev libonig-dev libopenexr-dev libopenjp2-7-dev libpango1.0-dev libpcre3-dev libpng-dev libpspell-dev libqdbm-dev libraqm-dev libraw-dev libreadline-dev librsvg2-dev libsasl2-dev libsodium-dev libssh2-1-dev libssl-dev libsqlite3-dev libsystemd-dev libtidy-dev libtool libwebp-dev libwmf-dev libx265-dev libxml2-dev libxpm-dev libxslt1-dev libzip-dev libzstd-dev make poppler-utils ragel re2c yasm zlib1g-dev DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends install -y autoconf automake bison cmake g++ gcc ghostscript gnupg libaom-dev `apt-cache search --names-only 'libargon2(-0)?-dev' | awk '{print $1;}' | head -n1` libbrotli-dev libbz2-dev libc-client2007e-dev libcurl4-openssl-dev libde265-dev libdjvulibre-dev libedit-dev `apt-cache search --names-only 'libenchant(-2)?-dev' | awk '{print $1;}' | head -n1` libffi-dev `apt-cache search --names-only libfreetype6?-dev | awk '{print $1;}' | head -n1` libfftw3-dev libfribidi-dev libgd-dev libgmp-dev libgpg-error-dev libgpgme-dev libharfbuzz-dev libheif-dev libkrb5-dev libldap2-dev liblmdb-dev liblqr-1-0-dev libmariadb-dev libonig-dev libopenexr-dev libopenjp2-7-dev libpango1.0-dev libpcre3-dev libpng-dev libpspell-dev libqdbm-dev libraqm-dev libraw-dev libreadline-dev librsvg2-dev libsasl2-dev libsodium-dev libssh2-1-dev libssl-dev libsqlite3-dev libsystemd-dev libtidy-dev libtool libwebp-dev libwmf-dev libx265-dev libxml2-dev libxpm-dev libxslt1-dev libzip-dev libzstd-dev make poppler-utils ragel re2c yasm zlib1g-dev

View File

@ -5,7 +5,7 @@ const DBUSER='hosting'; // Database user
const DBPASS='MY_PASSWORD'; // Database password const DBPASS='MY_PASSWORD'; // Database password
const DBNAME='hosting'; // Database const DBNAME='hosting'; // Database
const PERSISTENT=true; // Use persistent database conection true/false const PERSISTENT=true; // Use persistent database conection true/false
const DBVERSION=20; //database layout version const DBVERSION=21; //database layout version
const CAPTCHA=1; // Captcha difficulty (0=off, 1=simple, 2=moderate, 3=extreme) const CAPTCHA=1; // Captcha difficulty (0=off, 1=simple, 2=moderate, 3=extreme)
const ADDRESS='dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion'; // our own address const ADDRESS='dhosting4xxoydyaivckq7tsmtgi4wfs3flpeyitekkmqwu4v4r46syd.onion'; // our own address
const CANONICAL_URL='https://hosting.danwin1210.me'; // our preferred domain for search engines const CANONICAL_URL='https://hosting.danwin1210.me'; // our preferred domain for search engines
@ -139,14 +139,6 @@ bindtextdomain('hosting', __DIR__.'/locale');
bind_textdomain_codeset('hosting', 'UTF-8'); bind_textdomain_codeset('hosting', 'UTF-8');
textdomain('hosting'); 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 { function get_onion_v3(string $sk) : string {
if(PHP_INT_SIZE === 4){ if(PHP_INT_SIZE === 4){
$pk = ParagonIE_Sodium_Core32_Ed25519::sk_to_pk($sk); $pk = ParagonIE_Sodium_Core32_Ed25519::sk_to_pk($sk);
@ -420,47 +412,7 @@ function private_key_to_onion(string $priv_key) : array {
$onion = ''; $onion = '';
$priv_key = trim($priv_key); $priv_key = trim($priv_key);
$version = 0; $version = 0;
if(($pkey = openssl_pkey_get_private($priv_key)) !== false){ if(($priv = base64_decode($priv_key, true)) !== 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){
$version = 3; $version = 3;
if( ! str_starts_with( $priv, '== ed25519v1-secret: type0 ==' . hex2bin( '000000' ) ) || strlen($priv) !== 96){ if( ! str_starts_with( $priv, '== ed25519v1-secret: type0 ==' . hex2bin( '000000' ) ) || strlen($priv) !== 96){
$message = 'Error: v3 secret key invalid.'; $message = 'Error: v3 secret key invalid.';
@ -478,11 +430,7 @@ function private_key_to_onion(string $priv_key) : array {
function generate_new_onion(int $version = 3) : array { function generate_new_onion(int $version = 3) : array {
$priv_key = ''; $priv_key = '';
$onion = ''; $onion = '';
if($version === 2){ if($version === 3){
$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 {
$seed = random_bytes(32); $seed = random_bytes(32);
$sk = ed25519_seckey_expand($seed); $sk = ed25519_seckey_expand($seed);
$priv_key = base64_encode('== ed25519v1-secret: type0 ==' . hex2bin('000000') . $sk); $priv_key = base64_encode('== ed25519v1-secret: type0 ==' . hex2bin('000000') . $sk);

View File

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

View File

@ -74,7 +74,7 @@ if($_SERVER['REQUEST_METHOD']==='POST'){
} }
} }
}else{ }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']; $onion_version = $_REQUEST['onion_type'];
} }
$check=$db->prepare('SELECT null FROM onions WHERE onion=?;'); $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><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> <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="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'); ?> <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"> <textarea id="private_key" name="private_key" rows="5" cols="28">
<?php echo isset($_REQUEST['private_key']) ? htmlspecialchars($_REQUEST['private_key']) : ''; ?> <?php echo isset($_REQUEST['private_key']) ? htmlspecialchars($_REQUEST['private_key']) : ''; ?>

View File

@ -156,6 +156,9 @@ if(!$version){
if($version<20){ if($version<20){
$db->exec("ALTER TABLE onions CHANGE max_streams max_streams tinyint(3) unsigned NOT NULL DEFAULT '6';"); $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=$db->prepare("UPDATE settings SET value=? WHERE setting='version';");
$stmt->execute([DBVERSION]); $stmt->execute([DBVERSION]);
} }