torcontrol: Query Tor for correct -onion configuration #15423

pull luke-jr wants to merge 1 commits into bitcoin:master from luke-jr:tor_socks_port changing 2 files +71 −19
  1. luke-jr commented at 4:48 pm on February 16, 2019: member

    Currently, we just assume any running Tor instance provides localhost port 9050 for SOCKS, and configure -onion accordingly when we get a Tor control connection.

    This actually queries the Tor node for its SOCKS listeners, and uses the configured port instead.

    For backward compatibility, it falls back to localhost:9050 if it can’t get any better port info. I’m not sure if that’s the correct action to take when the Tor daemon explicitly says there are no ports listening…

  2. DrahtBot commented at 4:51 pm on February 16, 2019: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    No conflicts as of last run.

  3. in src/torcontrol.cpp:344 in 962f168a01 outdated
    482@@ -481,6 +483,53 @@ TorController::~TorController()
    483     }
    484 }
    485 
    486+void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlReply& reply)
    487+{
    488+    // NOTE: We can only get here if -onion is unset
    


    practicalswift commented at 10:04 pm on February 16, 2019:
    Assert that condition?

    laanwj commented at 3:01 pm on June 5, 2019:
    Not necessary IMO.
  4. fanquake added the label P2P on Feb 16, 2019
  5. in src/torcontrol.cpp:342 in 962f168a01 outdated
    482@@ -481,6 +483,53 @@ TorController::~TorController()
    483     }
    484 }
    485 
    486+void TorController::get_socks_cb(TorControlConnection& _conn, const TorControlReply& reply)
    


    practicalswift commented at 10:20 am on February 17, 2019:
    Make sure parameter names match between declaration and definition :-)

    luke-jr commented at 3:07 am on February 18, 2019:
    I don’t agree with that aesthetic.
  6. kristapsk commented at 9:36 pm on May 14, 2019: contributor
    Agree with @practicalswift comments, apart from that tACK 962f168a014af659feea0a7d6153e4c2b57cf2ed (enabled/disabled 9050 and other ports in torrc, compared behaviour between 0.18 and this).
  7. laanwj commented at 2:59 pm on June 5, 2019: member
    Concept ACK, thanks, this makes sense.
  8. in src/torcontrol.cpp:372 in 962f168a01 outdated
    511+            LogPrint(BCLog::TOR, "tor: Get SOCKS port command yielded %s\n", socks_port_str);
    512+        } else {
    513+            LogPrintf("tor: Get SOCKS port command returned nothing\n");
    514+        }
    515+    } else if (reply.code == 510) {  // 510 Unrecognized command
    516+        LogPrintf("tor: Get SOCKS port command failed with unrecognized command (You probably should upgrade Tor)\n");
    


    laanwj commented at 3:17 pm on June 6, 2019:
    Do you know what is the minimum version of Tor supporting this query? is it newer or older than what we already require? (not that it matters much, as I se it’ll gracefully fall back to the old behavior; but it might be useful for testing)

    Saibato commented at 11:06 am on June 26, 2020:

    Do you know what is the minimum version of Tor supporting this query? is it newer or older than what we already require? (not that it matters much, as I se it’ll gracefully fall back to the old behavior; but it might be useful for testing)

    Tyi: This info call /net/listeners/socks is according to tor doku possible since [ 0.2.2.26-beta.] I tested with versions 0.2.9.16 and 0.4.3.5

    Changes in tor version 0.2.2.32 - 2011-08-27

    o Minor features (controller interface): - New “GETINFO net/listeners/(type)” controller command to return a list of addresses and ports that are bound for listeners for a given connection type. This is useful when the user has configured “SocksPort auto” and the controller needs to know which port got chosen. Resolves another part of ticket 3076. - Have the controller interface give a more useful message than “Internal Error” in response to failed GETINFO requests.

  9. kristapsk commented at 10:41 pm on November 13, 2019: contributor
    This came up in a twitter discussion with @luke-jr yesterday. What’s blocker here? Or just forgot in a long list of unmerged PRs?
  10. Empact commented at 9:46 am on January 6, 2020: member
    Concept ACK
  11. DrahtBot closed this on Mar 9, 2020

  12. DrahtBot commented at 8:34 pm on March 9, 2020: member
  13. DrahtBot reopened this on Mar 9, 2020

  14. in src/torcontrol.cpp:452 in 962f168a01 outdated
    572@@ -524,10 +573,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
    573         // Now that we know Tor is running setup the proxy for onion addresses
    574         // if -onion isn't set to something else.
    575         if (gArgs.GetArg("-onion", "") == "") {
    576-            CService resolved(LookupNumeric("127.0.0.1", 9050));
    577-            proxyType addrOnion = proxyType(resolved, true);
    578-            SetProxy(NET_ONION, addrOnion);
    579-            SetReachable(NET_ONION, true);
    580+            _conn.Command("GETINFO net/listeners/socks", std::bind(&TorController::get_socks_cb, this, std::placeholders::_1, std::placeholders::_2));
    


    Saibato commented at 10:38 am on June 26, 2020:

    Minor Nit it does not account for early user -proxy= settings and would overrule them.

    Please consider the litle patch ff That would also fix finally #14722 and make #19358 obsolete.

     0diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
     1index 2871f9030..dff873ce9 100644
     2--- a/src/torcontrol.cpp
     3+++ b/src/torcontrol.cpp
     4@@ -573,7 +573,8 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
     5 
     6         // Now that we know Tor is running setup the proxy for onion addresses
     7         // if -onion isn't set to something else.
     8-        if (gArgs.GetArg("-onion", "") == "") {
     9+        proxyType addrOnion;
    10+        if (gArgs.GetArg("-onion", "") == "" && !GetProxy(NET_ONION, addrOnion)) {
    11             _conn.Command("GETINFO net/listeners/socks", std::bind(&TorController::get_socks_cb, this, std::placeholders::_1, std::placeholders::_2));
    12         }
    13 
    

    luke-jr commented at 10:13 pm on July 8, 2021:
    It would be incorrect behaviour.
  15. Saibato changes_requested
  16. DrahtBot added the label Needs rebase on Mar 3, 2021
  17. in src/torcontrol.cpp:352 in 962f168a01 outdated
    491+        for (const auto& line : reply.lines) {
    492+            if (0 == line.compare(0, 20, "net/listeners/socks=")) {
    493+                const std::string port_list_str = line.substr(20);
    494+                std::vector<std::string> port_list;
    495+                boost::split(port_list, port_list_str, boost::is_any_of(" "));
    496+                for (auto& portstr : port_list) {
    


    vasild commented at 5:38 am on March 11, 2021:
    0                for (const auto& portstr : spanparsing::Split(port_list_str, ' ')) {
    

    luke-jr commented at 10:17 pm on July 8, 2021:
    0torcontrol.cpp:340:80: error: no member named 'rbegin' in 'Span<const char>'; did you mean 'begin'?
    1                    if ((portstr[0] == '"' || portstr[0] == '\'') && (*portstr.rbegin() == '"' || *portstr.rbegin() == '\'')) {
    2                                                                               ^~~~~~
    

    vasild commented at 11:39 am on July 9, 2021:
    Ah, Span has begin(), but no rbegin(). It has back() to lookup the last element, so *portstr.rbegin() can be replaced portstr.back() if you like it better.
  18. in src/torcontrol.cpp:498 in 962f168a01 outdated
    493+                const std::string port_list_str = line.substr(20);
    494+                std::vector<std::string> port_list;
    495+                boost::split(port_list, port_list_str, boost::is_any_of(" "));
    496+                for (auto& portstr : port_list) {
    497+                    if (portstr.empty()) continue;
    498+                    if ((portstr[0] == '"' || portstr[0] == '\'') && (*portstr.rbegin() == '"' || *portstr.rbegin() == '\'')) {
    


    vasild commented at 5:40 am on March 11, 2021:
    nit: this would accept "123' and '456". I guess it is ok, but is also easy to avoid, thus I mention it.
  19. in src/torcontrol.cpp:523 in 962f168a01 outdated
    518+        LogPrintf("tor: Get SOCKS port command failed; error code %d\n", reply.code);
    519+    }
    520+
    521+    if (socks_port_str.empty()) {
    522+        // Fallback to old behaviour
    523+        socks_port_str = "127.0.0.1";
    


    vasild commented at 5:46 am on March 11, 2021:
    nit: this is somewhat confusing because we assign a ...port.... variable an address, not a port. Maybe s/socks_port_str/socks_location/.
  20. vasild commented at 5:50 am on March 11, 2021: member
    Light code review ok. This is based on master from Feb 2019 and does not compile configure: error: openssl not found.. Needs rebase. I would like to compile and test it.
  21. luke-jr force-pushed on Jul 8, 2021
  22. luke-jr commented at 10:28 pm on July 8, 2021: member
    Rebased, nits addressed
  23. DrahtBot removed the label Needs rebase on Jul 9, 2021
  24. in src/torcontrol.cpp:356 in d37d95a9ea outdated
    338+                boost::split(port_list, port_list_str, boost::is_any_of(" "));
    339+                for (auto& portstr : port_list) {
    340+                    if (portstr.empty()) continue;
    341+                    if ((portstr[0] == '"' || portstr[0] == '\'') && (*portstr.rbegin() == portstr[0])) {
    342+                        portstr = portstr.substr(1, portstr.size() - 2);
    343+                        if (portstr.empty()) continue;
    


    vasild commented at 4:44 pm on July 27, 2021:

    If portstr contains just " (it is a string with length 1), then this condition will evaluate to true. On the subsequent line portstr.size() - 2 will be -1 converted to size_t (will cause a warning by the integer sanitizer). Then substr(1, -1) will return an empty string and it will work as intended - continue; will be executed.

    But anyway, I think it is better to add one more condition to avoid the above: && portstr.size() >= 2


    luke-jr commented at 7:19 pm on December 17, 2021:
    Done
  25. in src/torcontrol.cpp:369 in d37d95a9ea outdated
    364+    if (socks_location.empty()) {
    365+        // Fallback to old behaviour
    366+        socks_location = "127.0.0.1";
    367+    }
    368+
    369+    CService resolved(LookupNumeric(socks_location, 9050));
    


    vasild commented at 4:52 pm on July 27, 2021:

    Would be good to check the result of LookupNumeric() in case some unexpected string was returned by the Tor server.

    0    CService resolved(LookupNumeric(socks_location, 9050));
    1
    2    if (!resolved.IsValid()) {
    3        // Fallback to old behaviour
    4        resolved = LookupNumeric("127.0.0.1", 9050);
    5    }
    

    unknown commented at 5:09 am on August 7, 2021:
    Port 9150 for Windows: #22651 (review)

    kristapsk commented at 2:13 pm on August 30, 2021:
    Is it really Windows default? Not confusing with Tor Browser’s default, which is 9150?

    unknown commented at 3:02 pm on August 30, 2021:

    Not confusing with Tor Browser’s default, which is 9150?

    Yes this is what I normally follow:

    Windows: Running Tor browser and using it as proxy Linux: Running Tor after installing with command: sudo apt install tor

    Running Tor as service on Windows involves some workaround which I am not sure many do or maybe I am not aware of other easier ways to do it: https://superuser.com/questions/1631178/how-to-configure-tor-as-service-on-windows


    luke-jr commented at 3:09 pm on August 30, 2021:

    9050 here serves two purposes:

    1. Fallback to old behaviour. This was always 9050.
    2. Default port if Tor’s API returns just an IP. Is there any reason to think it would ever be anything other than 9050?

    lano1106 commented at 6:16 am on August 31, 2021:

    Here is my torcfg settings

    0## Tor opens a SOCKS proxy on port 9050 by default -- even if you don't
    1## configure one below. Set "SOCKSPort 0" if you plan to run Tor only
    2## as a relay, and not make any local application connections yourself.
    3SOCKSPort 9050 # Default: Bind to localhost:9050 for local connections.
    4SOCKSPort 192.168.1.2:9050 # Bind to this address:port too.
    

    If only the port is provided, it is binded implicitly to 127.0.0.1. I need to test this patch to see the actual output but if what is printed by nyx is what is returned as-is by torcontrol, the config above would return:

    9050, 192.168.1.2:9050

    Your function wants to favor 127.0.0.1 but I think that it could miss the standalone port value scenario…


    lano1106 commented at 3:35 am on September 1, 2021:

    I have few more thoughts to share to possibly improve further the code of this function. Here is my setup:

    I have 1 tor proxy configured on a single machine in my LAN. It is on 192.168.1.2. This allows me to share a single tor proxy instance among all the trusted machines inside my LAN.

    Bitcoind is running on a different machine: 192.168.1.179.

    My first attempt to make torcontrol available for bitcoind was to bind the control listening socket to 192.168.1.2:9051. It works except that tor is complaining big time that this is opening a security risk as the control protocol exchange is in clear text over the network.

    To fix that, I did create a SSH tunnel between the 2 machines 127.0.0.1:9051.

    What that means is that when I start bitcoind from 192.168.1.179 machine with the cmdline: -proxy 192.168.1.2:9050 -torcontrol 127.0.0.1:9051

    When bitcoind connects with torcontrol, despite it is a localhost address, it does actually connect to a remote server.

    What all this means for this commit?

    Well, it favors the tor proxy address 127.0.0.1. With my setup, it will fail.

    The first solution to address this issue that came to my mind is to test that 127.0.0.1:9050 is listening but this is clumsy, there is no simple and portable way to check that beside actually connect a socket to the address…

    Then, I did ask myself the following question: What are exactly the benefits of connecting to the localhost proxy address if present?

    I am not sure if there is any.

    OTOH, if you connect to the first public IP address listed in the reply, it will work with the most common case where the proxy is on the same machine and it will also work on more funky setups like mine…

    How do you feel toward this suggestion? Does that makes sense to you?


    vasild commented at 1:44 pm on September 2, 2021:

    I tested with

    0SOCKSPort 10000
    1SOCKSPort 192.168.0.1:20000
    2SOCKSPort 0.0.0.0:30000
    

    The reply from the Tor control daemon is:

    0net/listeners/socks="127.0.0.1:10000" "192.168.0.1:20000" "0.0.0.0:30000"
    

    so it does not return just port. The spec is here: https://github.com/torproject/torspec/blob/845a4d7213e8e28bb039d6925437b5b1c0d607e7/control-spec.txt#L912.

    Maybe it makes sense to choose the non-127.0.0.1 address if there are a few:

    1. If the Tor daemon is on the same machine as bitcoind, then either one will work and communication will be local anyway
    2. If the Tor daemon is on another machine, only the non-127.0.0.1 address will work.

    But anyway - we can’t expect the automatic configuration to detect and work in all cases. For this we have the manual override. @lano1106, in your case you can set -onion=192.168.1.2:9050 which will work with master and with this PR.


    lano1106 commented at 2:00 pm on September 2, 2021:

    Vasil, you have been faster than me… I just tested too this morning: 2021-09-02T13:51:22Z tor: reply line: net/listeners/socks="127.0.0.1:9050" "192.168.1.2:9050"

    So overall this pull request works well. I just think non localhost address should be prefered over 127.0.0.1. This would work with my setup and I don’t see any extra benefits of picking 127.0.0.1 in any scenario.


    lano1106 commented at 2:38 pm on September 2, 2021:

    But anyway - we can’t expect the automatic configuration to detect and work in all cases. For this we have the manual override. @lano1106, in your case you can set -onion=192.168.1.2:9050 which will work with master and with this PR.

    you are correct but see my other suggestion below. I did configure the onion proxy with the following options: -proxy=192.168.1.2:9050 -torcontrol=127.0.0.1:9151

    I think that the condition: gArgs.GetArg("-onion", "") == ""

    should be changed with: !GetProxy(NET_ONION, addrOnion)

    because -onion switch is not the only way to configure the onion proxy. This is the root cause of my problem and why I got interested in this issue in the first place…


    luke-jr commented at 3:03 pm on September 2, 2021:

    So overall this pull request works well. I just think non localhost address should be prefered over 127.0.0.1. This would work with my setup and I don’t see any extra benefits of picking 127.0.0.1 in any scenario.

    The non-localhost address may change or cease to be available?

    because -onion switch is not the only way to configure the onion proxy.

    But it’s the only way that should override -torcontrol IMO


    lano1106 commented at 1:36 pm on September 3, 2021:

    @luke-jr if the non-localhost address may change or cease to be available is a serious and valid concern for not modifying the code behavior then so be it.

    I have said everything that I have to say on the topic and I’ll conclude by saying that without being aware of the initial problem that motivated this pull request, with the reasonable assumption that the vast majority of tor proxy setups will list the localhost address, this pull request, if left as-is, will just be a shinier, more complex method to essentially reach the exact same result than what the current code is doing…


    luke-jr commented at 7:18 pm on December 17, 2021:
    Fixed (without calling LookupNumeric with an empty string)
  26. vasild commented at 9:02 am on August 30, 2021: member
    @luke-jr, are you planning to update this PR?
  27. in src/torcontrol.cpp:451 in d37d95a9ea outdated
    415@@ -369,10 +416,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
    416         // Now that we know Tor is running setup the proxy for onion addresses
    417         // if -onion isn't set to something else.
    418         if (gArgs.GetArg("-onion", "") == "") {
    


    lano1106 commented at 3:22 am on September 1, 2021:

    This line did cause me a problem and this is why I created #22830

    In a nutshell, you could have the onion proxy set with the following cmdline: -proxy=192.168.1.2:9050 -torcontrol=127.0.0.1:9050

    I believe that check the presence of the -onion switch is not the right check because the check as-is overwrite the user settings.

    The code should instead call GetProxy() and only enter the conditional block if function returns false because the onion proxy is not currently valid.


    luke-jr commented at 7:14 pm on December 17, 2021:
    I think the current behaviour is correct.
  28. luke-jr force-pushed on Dec 17, 2021
  29. luke-jr commented at 7:19 pm on December 17, 2021: member
    Review comments addressed
  30. unknown approved
  31. unknown commented at 8:23 pm on December 17, 2021: none

    utACK https://github.com/bitcoin/bitcoin/pull/15423/commits/4314a216e319b70ab0b47969eae4d8ad86262f37

    nit: #15423 (review)

    I never used 9050 port on Windows and it was 9150 with browser. Not sure how many Bitcoin Core users run this software on Windows but Windows is still used for most of the desktop PCs and easiest process is to use 9150 which would work as default.

  32. vasild approved
  33. vasild commented at 1:23 pm on December 20, 2021: member
    ACK 4314a216e319b70ab0b47969eae4d8ad86262f37
  34. vasild commented at 1:27 pm on December 20, 2021: member
    I am not sure about the default socks port on Windows, but from the point of view of this PR it was 9050 before and is 9050 after, so it is ok, it is not the purpose of this PR to change that.
  35. DrahtBot added the label Needs rebase on Mar 1, 2022
  36. luke-jr force-pushed on Mar 15, 2022
  37. torcontrol: Query Tor for correct -onion configuration b2774fc0be
  38. luke-jr force-pushed on Mar 15, 2022
  39. luke-jr commented at 1:34 am on March 15, 2022: member
    Rebased again
  40. DrahtBot removed the label Needs rebase on Mar 15, 2022
  41. vasild approved
  42. vasild commented at 3:31 pm on March 15, 2022: member
    ACK b2774fc0bed53dfaf98206d353d42c474c5bbb1a
  43. in src/torcontrol.cpp:56 in b2774fc0be
    52@@ -53,6 +53,7 @@ static const float RECONNECT_TIMEOUT_EXP = 1.5;
    53  * this is belt-and-suspenders sanity limit to prevent memory exhaustion.
    54  */
    55 static const int MAX_LINE_LENGTH = 100000;
    56+static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050;
    


    jonatack commented at 9:13 pm on March 16, 2022:
    • s/const/constexpr/ if you retouch

    • as a follow-up, maybe use this constant in src/init.cpp

    • there is also

    0src/qt/optionsmodel.h:20:static constexpr uint16_t DEFAULT_GUI_PROXY_PORT = 9050;
    
  44. jonatack commented at 10:05 pm on March 16, 2022: member

    ACK b2774fc0bed53dfaf98206d353d42c474c5bbb1a review, rebased to master, debug build, ran unit tests, tested happy path only

    02022-03-16T21:31:10Z [torcontrol] tor: Authentication successful
    12022-03-16T21:31:10Z [torcontrol] tor: Get SOCKS port command yielded 127.0.0.1:9050
    22022-03-16T21:31:10Z [torcontrol] tor: Configuring onion proxy for 127.0.0.1:9050
    32022-03-16T21:31:10Z [torcontrol] tor: ADD_ONION successful
    
  45. laanwj commented at 8:22 am on March 22, 2022: member

    I never used 9050 port on Windows and it was 9150 with browser.

    This has nothing to do with Windows. Tor Browser’s internal Tor uses port 9150 on every OS. This is an implementation detail and it is frowned upon to use it in third-party applications (it controls circuits tightly, for example, so anything interfering with it might accidentally affect privacy). The normal Tor version for windows uses the same default port, 9050.

  46. laanwj commented at 10:47 am on March 22, 2022: member

    Tested ACK (FreeBSD) b2774fc0bed53dfaf98206d353d42c474c5bbb1a

    I changed SocksPort temporary and restarted bitcoind to see if it’d pick it up. And it did.

    tor:

    0Mar 22 11:45:33.942 [notice] Opening Socks listener on 127.0.0.1:9066
    1Mar 22 11:45:33.943 [notice] Opened Socks listener connection (ready) on 127.0.0.1:9066
    

    bitcoind:

    02022-03-22T10:46:20Z tor: Get SOCKS port command yielded 127.0.0.1:9066
    12022-03-22T10:46:20Z tor: Configuring onion proxy for 127.0.0.1:9066
    
  47. laanwj merged this on Mar 22, 2022
  48. laanwj closed this on Mar 22, 2022

  49. laanwj referenced this in commit 8b7b630ea9 on Mar 22, 2022
  50. fanquake referenced this in commit 7647acee16 on Mar 22, 2022
  51. sidhujag referenced this in commit 118b64c081 on Mar 23, 2022
  52. DrahtBot locked this on Mar 22, 2023

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-03 16:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me