Tor hidden services allow various types of services (web server, telnet server, chat server, etc) to be operated within the Tor network. This allows both users and service operators to conceal their identities and locations. Just about anything that can be run on the clearnet can be run within the Tor deepweb.
Setting up a hidden service on Tor is a simple process and depending on the level of detail, an operator can keep their service completely anonymous. Depending on your use-case, you may or may not choose to anonymize your service at all. For anonymous operation, it is recommended to bind services being offered to localhost and make sure that they do not leak information such as an IP address or hostname in any situation (such as with error messages).
For this guide, we assuming a Debian "Buster" system.
It is recommended to use an instance in a VirtualBox, so that you don't litter your main operating system and that you can start all over if something went wrong.
The following introduction is for educational purpose only.
Before configuring a relay, the Tor package must be set up on the system. While Debian does have a Tor package in the standard repositories, we will want to add the official Tor repositories and install from there to get the latest software and be able to verify its authenticity.
First, we will edit the sources list so that Debian will know about the official Tor repositories.
sudo nano /etc/apt/sources.list
At the bottom of the file, paste the following two lines and save/exit.
deb http://deb.torproject.org/torproject.org buster main
deb-src http://deb.torproject.org/torproject.org buster main
Now back in the console, we will add the Tor Projectâs GPG key used to sign the Tor packages. This will allow verification that the software we are installing has not been tampered with.
wget https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc
apt-key add <A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc
Remove the key file:
rm -r A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc
Lastly, run an update and install Tor from the repositories we just added.
apt-get update
apt-get install tor deb.torproject.org-keyring
We'll install the dependencies and the 3rd party repository called Sury for PHP 8.
sudo apt install apt-transport-https lsb-release ca-certificates wget curl -y
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
Adding the GPG key and updating the packages.
curl -sSL -o /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sudo apt update
Now it is time to install PHP 8:
sudo apt install php8.0 php8.0-fpm php8.0-curl php8.0-mysqlnd php8.0-zip php8.0-mbstring php8.0-bcmath php8.0-gd php8.0-xml -y
We are installing the required packages and adding the signing key to the system.
sudo apt install -y software-properties-common dirmngr
sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8
Now we are adding the MariaDB repository.
sudo add-apt-repository 'deb [arch=amd64] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.4/debian buster main'
Update the packages and install MariaDB
sudo apt update
sudo apt install -y mariadb-server mariadb-client
Run sudo mysql_secure_installation command to do initial set up to secure MariaDB installation.
sudo mysql_secure_installation
We will now get asked different questions. Follow the instructions:
We will be editing the torrc file, so letâs bring it up in our text editor:
sudo nano /etc/tor/torrc
Going line by line in this file is tedious, so to minimize confusion, we will ultimately rewrite the whole file. We will implement logging into a file located at /var/log/tor/notices.log and assume the local machine has a web server running on port 80. Paste the following over the existing contents in your torrc file:
Log notice file /var/log/tor/notices.log
HiddenServiceDir /var/lib/tor/my_service/
HiddenServicePort 80 127.0.0.1:80
HiddenServicePort 81 127.0.0.1:81
HiddenServicePort 22 127.0.0.1:22
After saving the file, make and permission a log file, then we are ready to restart Tor:
sudo touch /var/log/tor/notices.log
chown debian-tor:debian-tor /var/log/tor/notices.log
sudo service tor restart
If the restart was successful, the Tor hidden service is active. If not, be sure to check the log file for hints as to the failure:
sudo nano /var/log/tor/notices.log
There is a hostname file at /var/lib/tor/my_service/hostname that contains the hidden serviceâs public key. This public key acts as a .onion address which users on the Tor network can use to access your service. Make a note of this address after reading it from the file with cat:
sudo cat /var/lib/tor/my_service/hostname
Output: qwr...pid.onion
There is also a private_key file that contains the hidden serviceâs private key. This private key pairs with the serviceâs public key. It should not be known or read by anyone or anything except Tor, otherwise someone else will be able to impersonate the hidden service. If you need to move your Tor hidden service for any reason, make sure to backup the hostname and private_key files before restoring them on a new machine.
After restarting the hidden service, it may not be available right away. It can take a few minutes before the .onion address resolves on a client machine.
Let's use this hidden service to host a website with Nginx.
First, we will install Nginx and create a directory for our HTML files
sudo apt-get install nginx
sudo mkdir -p /var/www/hidden_service/
Now, we will create an HTML file to serve, so we need to bring one up in our editor:
sudo nano /var/www/hidden_service/index.html
Paste the following basic HTML and save it:
<html><head><title>Hidden Service</title></head><body><h1>It works!</h1></body></html>
Next, we will set the owner of the files we created to www-data for the web server and change the permissions on the /var/www directory.
sudo chown -R www-data:www-data /var/www/hidden_service/
sudo chmod -R 755 /var/www
We want to make some configuration changes for anonymity. First, let's edit the default server block:
sudo nano /etc/nginx/sites-available/default
Find the block that starts with server { and you should see a line below that reads listen 80 default_server;. Replace this line with to explicitly listen on localhost:
listen localhost:80 default_server;
Now find the line in the block for server_name set the server name explicitly:
server_name _;
Next we need to edit the Nginx configuration file:
sudo nano /etc/nginx/nginx.conf
Find the block that starts with http { and set the following options:
keepalive_timeout 300;
server_names_hash_bucket_size 128;
server_name_in_redirect off;
server_tokens off;
port_in_redirect off;
The first option will keep the server response time up to 5 minutes, which can be useful on slow connections. The second option is necessary so the server can resolve the long vanity v3 domain name. The third option will make sure the server name isn't used in any redirects. The forth option removes server information in error pages and headers. The fifth option will make sure the port number Nginx listens on will not be included when generating a redirect.
Now we need to create a server block so Nginx knows which directory to serve content from when our hidden service is accessed. Using our text editor, we will create a new server block file:
sudo nano /etc/nginx/sites-available/hidden_service
In the empty file, paste the following configuration block. Make sure that the server_name field contains your onion address which you read from the hostname file earlier and not my address, qwr...pid.onion.
server {
listen 127.0.0.1:80;
server_name qwr...pid.onion;
error_log /var/log/nginx/hidden_service.error.log;
access_log off;
root /var/www/hidden_service;
index index.php index.html index.htm;
server_tokens off;
location / {
allow 127.0.0.1;
deny all;
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
After saving the file, we need to symlink it to the sites-enabled directory and then restart Nginx:
sudo ln -s /etc/nginx/sites-available/hidden_service /etc/nginx/sites-enabled/hidden_service
sudo service nginx restart
To test the hidden service, download and install the Tor Browser on any machine and load up your .onion address.
Install PHP extensions for phpMyAdmin to connect with the database.
sudo apt install -y php-json php-mbstring php-xml
The phpMyAdmin package is now available in the Debian repository. But, we do not use it here since it is an older version. So, we will download the latest version from the official website.
wget https://files.phpmyadmin.net/phpMyAdmin/5.1.1/phpMyAdmin-5.1.1-all-languages.tar.gz
Extract phpMyAdmin using the tar command.
tar -zxvf phpMyAdmin-5.1.1-all-languages.tar.gz
Move the phpMyAdmin to your desired location.
sudo mv phpMyAdmin-5.1.1-all-languages /usr/share/phpMyAdmin
Copy the sample configuration file.
sudo cp -pr /usr/share/phpMyAdmin/config.sample.inc.php /usr/share/phpMyAdmin/config.inc.php
Edit the configuration file.
sudo nano /usr/share/phpMyAdmin/config.inc.php
Generate a blowfish secret and update the secret in the configuration file. Use your own secret!
$cfg['blowfish_secret'] = 'DjnEodjS37saeWAMg6sdeOPQX8RzeV8x'; /* YOU MUST FILL IN THIS FOR COOKIE AUTH! */
Also, uncomment the phpMyAdmin storage database and tables.
$cfg['Servers'][$i]['pmadb'] = 'phpmyadmin';
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['table_uiprefs'] = 'pma__table_uiprefs';
$cfg['Servers'][$i]['tracking'] = 'pma__tracking';
$cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
$cfg['Servers'][$i]['favorite'] = 'pma__favorite';
$cfg['Servers'][$i]['users'] = 'pma__users';
$cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
$cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
$cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
$cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
$cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
$cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';
Import the create_tables.sql to create tables for phpMyAdmin. Enter your MariaDB password for root.
sudo mysql < /usr/share/phpMyAdmin/sql/create_tables.sql -u root -p
Create a virtual host configuration file for phpMyAdmin under the /etc/nginx/conf.d directory.
sudo nano /etc/nginx/conf.d/phpMyAdmin.conf
Use the following information to create a virtual host for phpMyAdmin. Change the server_name as per your requirement.
server {
listen 81;
server_name qwr...pid.onion;
root /usr/share/phpMyAdmin;
location / {
index index.php;
auth_basic "Admin Area";
auth_basic_user_file /etc/apache2/.htpasswd;
}
## Images and static content is treated different
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
access_log off;
expires 30d;
}
location ~ /\.ht {
deny all;
}
location ~ /(libraries|setup/frames|setup/libs) {
deny all;
return 404;
}
location ~ \.php$ {
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/phpMyAdmin$fastcgi_script_name;
}
}
Create a tmp directory for phpMyAdmin and then change the permission.
sudo mkdir /usr/share/phpMyAdmin/tmp
sudo chmod 777 /usr/share/phpMyAdmin/tmp
Set the ownership of the phpMyAdmin directory.
sudo chown -R www-data:www-data /usr/share/phpMyAdmin
Now we will build another protection layer for the web interface using a .htpasswd-File.
First we have to make sure that we have the right tools installed.
sudo apt install apache2-utils
Now we create a password file and a first user. Run the htpasswd utility with the -c flag (to create a new file), the file pathname as the first argument, and the username as the second argument:
sudo htpasswd -c /etc/apache2/.htpasswd user1
Press Enter and type the password for user1 at the prompts.
Optionally: Create additional user-password pairs. Omit the -c flag because the file already exists:
sudo htpasswd /etc/apache2/.htpasswd user2
You can confirm that the file contains paired usernames and hashed passwords:
cat /etc/apache2/.htpasswd
Output:
Restart the services.
sudo systemctl restart nginx
sudo systemctl restart php8.0-fpm
You can access the phpMyAdmin web interface by going to the domain with an ending :81 like so qwr...pid.onion:81
Put in your .htpasswd credentials and than your MariaDB root credentials.
SFTP is built upon the SSH transport layer and should be installed on most Linux server distributions by default. If it isnât, you can install with:
sudo apt install ssh
Then change the Subsystem to internal-sftp in sshd_config.
sudo nano /etc/ssh/sshd_config
Scroll to the bottom of the file and comment out the line Subsystem sftp by adding # before it and then add Subsystem sftp internal-sftp below it.
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
This tells sshd to use SFTP server code built into sshd instead of running sftp-server, which is now redundant and only kept for a backward compatibility.
Restart the sshd service for changes to take affect.
sudo service sshd restart
Now we have to create a SFTP-User.
Itâs not recommended that you use the root account or any account with sudo privileges to upload files to the web server document root. For this reason, you should create a new user that only has SFTP access to the document root.
In this guide, we are calling the SFTP user sftpuser â you can call this whatever you want. If you plan to give SFTP access to multiple users across different document roots, consider a naming scheme like username_domain_com. For example admin_dennisosaj_de. This will make it easier to keep track of all your SFTP users.
For the purposes of this guide, we will name the SFTP user sftpuser.
sudo adduser sftpuser
Generate a password and press enter to accept all defaults.
Next we will create a Match User directive in the SSH config and add your SFTP user to the www-data group.
Restrict the user sftpuser to the document root and also disable their SSH access â we only want them to be able to log in over SFTP. We can do this by adding a Match User directive in the SSH config file.
Begin by opening sshd_config.
sudo nano /etc/ssh/sshd_config
Scroll down to the bottom of the SSH config file and add your new Match User directive.
Make sure that ChrootDirectory is the directory above your document root. For example, this guide's document root is /var/www/hidden_service/, then the ChrootDirectory is /var/www/.
Note you can add multiple users here separated by a comma, e.g. Match User sftpuser, sftpuser2, sftpuser3
Note: ForceCommand internal-sftp will force SFTP access only and not allow this SFTP user to log in via SSH.
Match User sftpuser
ChrootDirectory /var/www/
ForceCommand internal-sftp
X11Forwarding no
AllowTcpForwarding no
PasswordAuthentication yes
Test SSH config before restarting.
sudo sshd -t
If no errors, restart the sshd service for changes to take affect.
sudo service sshd restart
Next we have to add the SFTP user sftpuser to the www-data group.
sudo usermod -a -G www-data sftpuser
Note: Linux groups do not take affect until the user logs out and in again. If you are already logged in as this user in your FTP client, close the program completely and then log in again.
If you need to provide other SFTP users write access to the document root, simply add their usernames separated by a comma, e.g. Match User sftpuser, sftpuser2, sftpuser3 in sshd_config and then add the SFTP user to the www-data group.
Now you can login to your hidden service using SFTP. Make sure Tor is running on the machine from which you want to login and that the proxy settings are set in your FTP-client (e.g. FileZilla):
We are using a tool called mkp224o. So first of all download the repository using git.
git clone https://github.com/cathugger/mkp224o.git
Afterwards run:
apt install gcc libsodium-dev make autoconf
After you successfully downloaded the repository and necessary packages go into the directory with:
cd mkp224o
Now build and init the tool.
./autogen.sh
./configure
make
The generator needs one or more filters to work.
It makes directory with secret/public keys and hostname for each discovered service. By default root is current directory, but that can be overridden with -d switch.
Run it like ./mkp224o dennis, and it will try creating keys for onions starting with "dennis" in this example. To not litter current directory and put all discovered keys in directory named "keys" use:
./mkp224o -d keys dennis
Output:
You can use what ever letters you want, but stay under 5-6 letters, otherwise the search process will take to much computing power.
Wait some time and after it found one or multiple addresses, you can cancel the tool with ctrl + C.
Now we have to copy one of the generated folders with its content to where we want our service keys to reside. First go to the root directory.
cd ../
sudo cp -r mkp224o/keys/dennis...hjt.onion /var/lib/tor/custom
Replace dennis...hjt.onion with the full name of your directory which you created just now.
You may need to adjust ownership and permissions:
sudo chown -R debian-tor: /var/lib/tor/custom
sudo chmod -R u+rwX,og-rwx /var/lib/tor/custom
Go into the Tor config file and replace HiddenServiceDir /var/lib/tor/my_service/.
sudo nano /etc/tor/torrc
HiddenServiceDir /var/lib/tor/custom/
Now restart Tor to let it take effect.
sudo service tor restart
Next we have to change the server_name in the following files. Just replace the old .onion-address with the new one.
sudo nano /etc/nginx/sites-available/hidden_service
sudo nano /etc/nginx/conf.d/phpMyAdmin.conf
Restart the Server and wait a minute to to let the changes take effect.
sudo service nginx restart
Your Server is reachable from your custom .onion-address now. Congrats!
Um die Seite optimal gestalten und fortlaufend verbessern zu können und zur statistischen Auswertung, verwenden wir Cookies. NĂ€here Informationen dazu und zu Ihren Rechten als Benutzer finden Sie in unserer DatenschutzerklĂ€rung. Klicken Sie auf âIch stimme zuâ, um Cookies zu akzeptieren und direkt unsere Website besuchen zu können, oder klicken Sie auf âEinstellungen anpassenâ (am Ende des Cookie-Hinweises), um Ihre Cookies selbst zu verwalten.
Ich stimme zuHinweis zur Verarbeitung deiner auf dieser Webseite erhobenen Daten in den USA durch Google, Facebook, LinkedIn, Twitter, Youtube: indem du auf âIch stimme zu" klickst, willigst du zugleich dem. Art 49 Abs. 1 S. 1 lit. a DSGVO ein, dass deine Daten in den USA verarbeitet werden. Die USA werden vom europĂ€ischen Gerichtshof als ein Land mit einem nach EU-Standards unzureichendem Datenschutzniveau eingeschĂ€tzt. Es besteht insbesondere das Risiko, dass deine Daten durch US-Behörden, zu Kontroll- und zu Ăberwachungszwecken, möglicherweise auch ohne Rechtsbehelfsmöglichkeiten, verarbeitet werden können. Wenn du die verwendeten Cookies unter âEinstellungen anpassenâ abwĂ€hlst, dann findet die vorgehend beschriebene Ăbermittlung nicht statt.
Cookie Settings
Speichert Einstellungen, die hier getroffen werden. (1 Tag bis 2 Jahr)
Google Analytics | Google LLC | DatenschutzerklÀrung
Cookie von Google fĂŒr Website-Analysen. Erzeugt statistische Daten darĂŒber, wie der Besucher die Website nutzt. Alle Informationen werden anonymisiert gespeichert. (2 Jahre)