Custom tor2web service with Nginx and Lua


    Let's discuss how to make a gateway from the Internet to hidden Tor sites.

    The Tor network is a proxy system that allows you to establish an anonymous network connection. Using Tor, you can anonymously connect to regular servers and host unheard servers on the Tor network itself. In the latter case, a hidden server is created in the onion zone. The server name includes 16 letters and numbers (fingerprint).

    facebook mirror onion

    How can I go to hidden servers:

    1. install Tor and direct browser traffic through it. Tor browser is a portable application that includes everything you need;
    2. however, not all people install a Tor browser, so you need a way to show the contents of a hidden server to a regular network user. Tor2web services come to the rescue, providing direct access to hidden sites.

    The Hidden Wiki website ( kpvzxxbbraaigawj.onion ) can be opened in a regular browser ( ). If a user connects to the site via tor2web, then he loses anonymity in exchange for access to the hidden site without installing Tor. I will give a list of similar services, some of which have been closed.

    • * (3 servers)
    • *
    • *
    • * (disabled)
    • * (disabled)
    • * (disabled)
    • * (disabled)
    • * (disabled)

    Consider the existing ways to run the tor2web service, after which I will share my own.

    Project Tor2web-3.0?


    Tor2web-3.0 is an important part of the GlobaLeaks project , which facilitates the access of network users to hidden servers.

    Example site:

    3 servers are connected to the Tor2web-3.0 project. You can install Tor2web on your server and join their network. Disabled .lu and .to servers belong to the same people.

    Tor2web-3.0 is installed as a standalone service. The code is written in Python. There are practically no complaints about Tor2web-3.0, but I wanted to avoid an additional participant (user - Nginx - Tor2web-3.0 - Tor - target site). In addition, I do not like the network software written in Python.



    Polipo is an HTTP server that can redirect connections to a SOCK5 server. Previously, Polipo was used for this purpose as part of the Tor browser.

    One could build a chain: Nginx - Polipo - Tor. As in the case of Tor2web-3.0, an extra participant arises, since Nginx does not know how to proxy traffic through the SOCK5 server. In addition, for the normal display of sites, I would like to replace the onion-links in the server’s response with links to the gateway: s / .onion / .onion.xx /

    Nginx patch?

    There is a patch for Nginx that adds the ability to proxy traffic through the SOCK5 server. In fact, the SOCKS5 protocol is very simple, so it’s strange that there is still no official module. This solution looks tempting, but it has not been brought to mind: I would have to patch Nginx with every update. I would like to have a solution that works on regular Nginx from the Debian Wheezy box. In addition, there is no way to replace links in the server response.

    Writing a module for Nginx on Lua


    Nginx has long supported the ability to embed scripts on Lua. The Lua code provides a wide range of options, including manipulation of direct access sockets. Unfortunately, I did not find the module for connecting to the SOCKS5 server, so I wrote my own . For each request, a connection is established with the Tor program through port 9050, a SOCKS5 handshake passes, and the address of the target site is transmitted. After that, the socket is used as if it were a direct socket to the target site. The user's request is read into memory, edited and transmitted to the server. The server response is read, edited (replacing links) and transmitted to the user. All operations are non-blocking. I designed this part as a separate onion2web module .

    When connecting to the site for the first time, the user sees a stub with a confirmation form for entering the site. This is necessary so that it is impossible to include pictures from hidden services in the pages of regular sites.

    The socks5 module contains functions by which the socket is forwarded through the SOCK5 server. The functions are described on the module page . The onion2web module contains one handle_onion2web function that serves the tor2web gateway. An example of use is given below. It is possible to set the address and port of the torus and disable the confirmation form for entering the site.


    • implemented a very simple HTTP client version 1.0, in which keep-alive and compression of transmitted data are disabled.
    • The request and response are read entirely into memory, and then transferred to the recipient. This increases memory consumption and slows down the transfer of information, especially in the direction from the site to the user. I suspect that you need to communicate with the SOCKS5 server in a separate coroutine . There will be difficulties with the substitution of addresses in the server response (the boundary of the data blocks may fall on the address being replaced).
    • The stub form does not contain protection against CSRF and always redirects to the main page (it is better to redirect to the path that was originally opened).
    • The server response must be edited more carefully: replace links only in HTML and only in attributes.

    On this option, I stopped and used it for my tor2web gateway . The disadvantages of the site itself include the lack of SSL. I think there are other disadvantages. And in general, while the decision is rather a crutch.

    How to raise your tor2web gateway

    We need a domain, server and wildcard SSL-certificate for this domain.

    In the domain, you need to register all subdomains with the IP address of our server:
    DNS editor of the wonderful service

    On the server, you need Tor, Nginx with fresh ngx_lua and my onion2web module to connect to the SOCKS5 server from Nginx. Debian Wheezy has a nginx-extras package that contains too old ngx_lua. (This old ngx_lua does not support some of the methods used, for example, ngx.req.raw_header.) The version of nginx-extras from wheezy-backports contains a fairly fresh ngx_lua. The onion2web module can be installed via luarocks (this will automatically install the socks5 module as a dependency).

    Installation for Debian Wheezy:

    # echo deb wheezy-backports main > /etc/apt/sources.list.d/wheezy-backports.list
    # apt-get update
    # apt-get install tor luarocks nginx-extras/wheezy-backports
    # luarocks install onion2web

    In Nginx we create the following site:

    server {
        listen 80;
        server_name *;
        location / {
            default_type text/html;
            content_by_lua '

    The domain appears in the config in two places: server_name and inside the Lua code.

    The site is ready: Socks5

    module sources:
    onion2web module sources:

    Also popular now: