{"id":25545181,"url":"https://github.com/daisvke/ft_onion","last_synced_at":"2026-04-28T17:35:00.256Z","repository":{"id":277765490,"uuid":"929379764","full_name":"daisvke/ft_onion","owner":"daisvke","description":"This project sets up a Tor hidden service running inside a Docker container with Nginx for web hosting and SSH access.","archived":false,"fork":false,"pushed_at":"2025-03-26T23:28:03.000Z","size":715,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-30T08:56:36.419Z","etag":null,"topics":["docker","docker-compose","ft-onion","hidden-services","nginx-docker","onion-service","ssh-docker","tor","tor-docker"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/daisvke.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-02-08T12:14:38.000Z","updated_at":"2025-03-26T23:28:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"2e70915e-c769-42e5-8c73-0b99a9abca0d","html_url":"https://github.com/daisvke/ft_onion","commit_stats":null,"previous_names":["daisvke/ft_onion"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/daisvke/ft_onion","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daisvke%2Fft_onion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daisvke%2Fft_onion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daisvke%2Fft_onion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daisvke%2Fft_onion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/daisvke","download_url":"https://codeload.github.com/daisvke/ft_onion/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/daisvke%2Fft_onion/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32392300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T14:34:11.604Z","status":"ssl_error","status_checked_at":"2026-04-28T14:32:37.009Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-compose","ft-onion","hidden-services","nginx-docker","onion-service","ssh-docker","tor","tor-docker"],"created_at":"2025-02-20T08:18:07.912Z","updated_at":"2026-04-28T17:35:00.251Z","avatar_url":"https://github.com/daisvke.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ft_onion \n\n## **Description**\nThis project sets up a **Tor hidden service** running inside a secured Docker container with **Nginx** for web hosting and **SSH access**. The website hosted is called **Slate Notes**, which is a platform where users can write and store secret notes securely. This setup ensures that all communications are anonymized and protected, allowing users to maintain their privacy while managing their sensitive information.\u003cbr /\u003e\u003cbr /\u003e\n\nIt supports **two modes**:  \n1. **Persistent mode**: Keeps the same `.onion` address across restarts.  \n2. **Non-persistent mode**: Generates a new `.onion` address each time.  \n\n![Slate Note](screenshots/slate_note.png)\n---\n\n## **Setup instructions**\n\n### Requirements\n- Docker\n- Docker Compose\n- Make\u003cbr /\u003e\n\n### **1. Clone the repository**\n```sh\ngit clone https://github.com/daisvke/ft_onion.git\ncd ft_onion\n```\n\n### **2. Configure environment**\n#### **Adapt port numbers**\nIf you get the following error:\n```\nlisten tcp4 0.0.0.0:4242: bind: address already in use\n```\nUse a host port that is available by modifying the following macro from the `.env` file:\n```\nPORT_HOST_SSH=4243\n```\n\n#### **.env file to create**\nCreate a `.env` file from the example:  \n```sh\ncp .env.example .env\n```\nThen edit the `.env` file as needed.\n\n#### **Log files to create**\nYou will need this structure for log persistence:\n```sh\n├── logs\n│   ├── auth.log\n│   └── fail2ban.log\n```\n\n#### **SSH file to create**\nThis one for the persistence of the authorized SSH keys:\n\n```sh\n├── config\n│   ├── ssh\n│   │   └── authorized_keys\n```\nHere copy-paste the SSH keys (one key = one line) of the devices which SSH connections are authorized.\n\n#### Website intergration\nBy default, we have our Slate Notes website hosted on the container,\nbut you can add any other PHP or HTML website using the default configuration.\nJust place your web project at `html/my_project` and replace `slate` by `my_project` on configuration and Docker files.\n\n### 3. **Build the image and run the container**\n\nNow that we have all the necessary empty files, we have two modes in which we can run this project:\n\n#### **1. Persistent Onion address**\n- You will need this structure (from /var/lib/tor/hidden_service/) to run it with hostname persistence:\n```sh\n├── tor_data\n    ├──hidden_service\n    ├──saved_hidden_service\n        ├── authorized_clients\n        ├── hostname # Contains the .onion address \n        ├── hs_ed25519_public_key\n        └── hs_ed25519_secret_key\n```\n\n- If you run the project for the first time, you will need to populate `tor_data/saved_hidden_service`:\n```sh\n# Run the container. This will generate the necessary files in the container.\nmake\n\n# Export the hidden_service files from the container to the host (`tor_data/hidden_service_export/`)\nmake tor-export\n\n# The files then need to be saved in the host folder `tor_data/saved_hidden_service/`.\ncp tor_data/hidden_service_export tor_data/saved_hidden_service\n```\n- Then, or if you already have the files in the right place, do:\n```sh\nmake\n```\nTo start the project and Tor with the saved parameters.\u003cbr /\u003e\nThis will keep the same **.onion** address across restarts.  \n\n#### **2. Non-persistent Onion address**\n```sh\nmake nonpersist\n\n# Or, if `tor_data/saved_hidden_service/` is empty:\nmake\n```\nA new **.onion** address will be generated on every restart.\n\n```sh\ndocker compose down\n# Or\nmake clean\n# Or do a full clean:\nmake fclean\n```\nThese will remove the `.onion` address across restarts.\n\n---\n\n## **Accessing the services**\n\n### **Find Your `.onion` Address**\nAfter starting the container, check your **Tor Hidden Service address**:  \n```sh\ndocker exec -it tor_service cat /var/lib/tor/hidden_service/hostname\n```\nUse **Tor Browser** to visit the site.\n\n### **SSH into the container (2 modes)**\n- When using `SSH (Secure Shell)` to connect to remote servers, there are two primary modes of operation you can consider: **Direct SSH Connection** and **SSH over Tor (using torsocks)**.\n\n- `torsocks` is a wrapper for applications that need to connect to the internet through the Tor network. It allows these applications to route their traffic through Tor, providing anonymity and privacy for the user.\u003cbr /\u003e\n\nHere’s the corrected version of your statement for clarity and accuracy:\n\n- **To use either of the two connection modes you can**:\n  - Add the SSH key of the device you want to connect from to the `authorized_keys` file on the host. This will automatically connect the device on login.\n  - Or, in `config/ssh/sshd_config`, change the following line:\n  ```\n  PasswordAuthentication no\n  ```\n  to `yes`. This will allow SSH connection with a password authentication.\n\n#### **1. To connect via SSH over Tor using torsocks**\n```bash\n# Install torsocks\nsudo apt install torsocks\n# Set up a Tor connection\nsudo tor\n# Connect to the server via SSH through the Tor network\ntorsocks ssh \u003cSSH_USER\u003e@\u003cONION_ADDRESS\u003e -p \u003cPORT_TOR_SSH\u003e # This is the port given in `torrc` host file\n```\n\n* **Pros**:\n\t- **Anonymity**: Connecting through Tor provides anonymity for both the client and the server. The server's IP address is not exposed to the client.\n\t- **Access from Anywhere**: You can access the server from anywhere without needing to expose your server's IP address to the public internet.\n\n* **Cons**:\n    - **Latency**: Tor can introduce additional latency due to the multiple hops your connection makes through the Tor network.\n\n#### **2. Using Direct SSH to the server's IP Address**\n```bash\n# Execute bash from the container\ndocker exec -it tor_service /bin/bash\n\n# Connect to the container via SSH from the host\nssh -p \u003cPORT_HOST_SSH\u003e \u003cSSH_USER\u003e@localhost\n# Ex.:\nssh -p 4242 user@localhost\n\n# Connect from another device on the same network\nssh -p \u003cPORT_HOST_SSH\u003e \u003cSSH_USER\u003e@\u003cTOR_SERVICE_HOST_PRIVATE_IP\u003e\n# Ex.:\nssh -p 4242 user@192.168.43.67\n```\n\n* **Pros**:\n    - **Performance**: A direct SSH connection to an IP address typically offers better performance and lower latency.\n\n* **Cons**:\n    - **Exposure**: The server's IP address is exposed, which can make it a target for attacks. If the server is on a public network, it may be vulnerable to scanning and unauthorized access.\n    - **Limited Access**: If you're trying to access the server from outside the local network, you may need to configure port forwarding on your router or use a VPN.\n\n#### **Check connections**\nConnections can be checked with the `w` command from the container:\n```\nroot@x:/# w\n 13:22:22 up 19:20,  2 users,  load average: 0.41, 0.66, 0.71\nUSER      TTY      FROM             LOGIN@   IDLE   JCPU    PCPU WHAT\nuser1     pts/0    172.18.0.1       13:20    1:26   0.00s   ?    -bash\nuser2     pts/1    127.0.0.1        13:22    4.00s  0.00s   ?    -bash\n```\n- Here `user1` is connected with a regular SSH connection and `user2` with a SSH over Tor connection.\n- It says `user2` is connected from localhost 127.0.0.1 because we have in `torrc`:\n```\nHiddenServicePort 4242 127.0.0.1:4242\n```\nThis tells the Tor service to direct connections from the Tor network to port 4242 of the local service. \n\n#### SSH fortification\nWe secured the SSH service against attacks by adding to our `sshd_config` file:\n```sh\n# Disable root login: Prevent attackers from trying to log in as root.\nPermitRootLogin no\n# Allow only specific users to log in via SSH\nAllowUsers user\n```\n\n**2. Enable verbose logging**:\n```sh\n# Install syslog (from Dockerfile)\napt update \u0026\u0026 apt install -y inetutils-syslogd\n\n# Run syslog (from script.sh)\nsyslogd\n\n# Add in `sshd_config`:\nSyslogFacility AUTH\nLogLevel VERBOSE  # With `INFO` we didn't get any SSH access logs\n\n# Check logs\ndocker exec -it tor_service cat /var/log/auth.log\ncat /var/run/utmp\n```\n\n**3. Prevent brute-force attacks by banning IPs after failed login attempts (Fail2ban)**:\n```sh\n# Install Fail2ban\napt update \u0026\u0026 apt install -y fail2ban\n\n# Edit config file\nvim config/jail.conf\n\n# We need to add a capability on the docker compose file\n# to run the container with networking permissions.\n# This is because `iptables` doesn't run without those permissions.\ncap_add:\n\t- NET_ADMIN\n\n# In jail.conf we must have:\n[sshd]\n\nport    = 4242\nlogpath = %(sshd_log)s\nbackend = %(sshd_backend)s\n\n# Run Fail2ban\nservice fail2ban start\n\n# Check status (total failed, total banned, etc)\nfail2ban-client status sshd\n\n# Display logs\ncat /var/log/fail2ban.log\n\n# Ban the IP Address\nfail2ban-client set \u003cJAIL_NAME\u003e banip \u003cIP_ADDRESS\u003e\n\n# Unban the IP Address\nfail2ban-client set \u003cJAIL_NAME\u003e unbanip \u003cIP_ADDRESS\u003e\n```\n\n![SSL \u0026 Fail2ban Authentication preview](screenshots/auth.png)\nThe address `192.168.16.1` is being banned.\n\n#### Ban persistency\n- fail2ban rules are persistent if you keep the `logs/auth.log` file intact on the host.\n\n**4. Use Key-Based Authentication**:\u003cbr /\u003e\n- If not done yet, generate an SSH key pair on your local machine:\n```sh\nssh-keygen\n```\n- Copy the public key to `config/ssh/authorized_keys` on the host machine\n\n```sh\n{ printf \"\\n\"; cat ~/.ssh/id_rsa.pub; } \u003e\u003e ./config/ssh/authorized_keys\n```\n- This will add an entry to `/home/user/.ssh/authorized_keys` in the container, and to `config/ssh/authorized_keys` on the host machine. Now the client can connect automatically to the server without having to log in.\n\n- Disable password authentication in the /etc/ssh/sshd_config file:\n\n```sh\nPasswordAuthentication no\n```\nPut back `yes` if you want to register a new user.\n\n##### **To unlog a user from its SSH connection**\n```sh\n# find the PID of the process managing the SSH session\nps aux | grep ssh\n# Kill the process\nkill \u003cPID\u003e\n# Connection is then closed\n```\n\n##### **Accessing through Tor socket**\nIn our case `Fail2Ban` wasn't detecting SSH login failures over Tor socket. This is because of how Tor handles connections and how Fail2Ban reads logs:\n  - when using Tor, **all connections appear to come from 127.0.0.1 (localhost)** because Tor is **forwarding** the request.\n  - Therefore, we needed to ignore login failures coming from the localhost:\n\n  ```sh\n  # In `jail.conf`:\n  ignoreip = 127.0.0.1/8 ::1\n  ```\n  `::1` is the **IPv6 loopback address**, equivalent to `127.0.0.1` in **IPv4**.\n\n### About HTTPS and the Tor network\nYou do not need `HTTPS` for a Tor `.onion` website because Tor already **encrypts all traffic end-to-end**. Unlike the regular internet, where HTTPS is needed to prevent MITM (Man-in-the-Middle) attacks, Tor's network ensures that:\t\n  - End-to-end encryption is built into the protocol.\n  - No need for TLS/SSL certificates (Let's Encrypt does not issue .onion certs).\n  - Traffic is encrypted between the client and the hidden service.\n  - When you are hosting a .onion Hidden Service, nobody (including exit nodes) can see your traffic because it stays inside the Tor network.\n---\n\n## Useful commands\n```sh\n# Check logs from the container\ndocker logs tor_service\n\n# Copy a local file into container\ndocker cp ./some_file tor_service:/work\n# Copy files from container to local path\ndocker cp tor_service:/var/logs/ /tmp/app_logs\n\n# Check the used ports inside the container with the corresponding processes\ndocker exec -it tor_service ss -tulnp\n\n# Check ports of the container that are open to the outside\ndocker ps\n# or\ndocker port \u003cCONTAINER ID\u003e\n\n# Check Nginx config file syntax and run test\ndocker exec -it tor_service nginx -t\n\n# Start a tiny temporary container, give it access to the current directory,\n# delete tor_data from inside the container, then throw the container away\ndocker run --rm -v $(pwd):/data busybox rm -rf /data/tor_data\n```\n\n## Screenshot\n![tor service preview](screenshots/tor_service.png)\n\n## References\n* [Set up Your Onion Service (torproject.org)](https://community.torproject.org/onion-services/setup/)\n* [docker-compose reference YAML file with comments](https://gist.github.com/ju2wheels/1885539d63dbcfb20729)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaisvke%2Fft_onion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdaisvke%2Fft_onion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdaisvke%2Fft_onion/lists"}