Search code examples
haskellproxyconnectionsockstor

Haskell SOCKS5 Refusing to Connect


I have been working on this problem for weeks but just can't seem to get it... I've been trying to write a Haskell program that connects to a socks5 proxy (namely tor), so that way I can access onion sites from within the program, but it's not working.

To give you the layout, I have tor running on localhost@9050 and it certainly works because I can configure my browser to work with it through socks5. Privoxy is not running.

The source code is:

import Network
import Network.Socket
import Network.Socks5

    getonion :: IO ()
    getonion = do
            putStrLn "Connecting..."
            sock <- socksConnectWith (defaultSocksConf "localhost" (PortNum 9050)) "exampleonion.onion" (PortNumber 80)
            putStrLn "Connected!"

Every time I run getonion, it always results in:

Connecting...
*** Exception: connect: does not exist (Connection refused)

I've tried connecting to localhost using all sorts of ways, namely the other functions referenced here and here, but socksConnectWith seemed the most straightforward.

If anyone could help me figure this out it would be much appreciated. I could even post the wireshark packets that come from my program to localhost. Thank you.


Solution

  • Instead of using the PortNum constructor, just write the port number in the source file:

    sock <- socksConnectWith (defaultSocksConf "localhost" 9050) "exampleonion.onion" (PortNumber 80)
    

    Notice how in fact you're already doing this with PortNumber 80, since the constructor PortNumber actually takes an argument of type PortNumber, not Word16 (it produces a PortID; unfortunately, types and constructors are allowed to have the same names even if they are otherwise unrelated).

    In Haskell, integer literals like the above are short for (say) fromInteger 80, and the fromInteger function (from the Num type class, of which PortNumber is an instance) converts the given integer to network byte order for you – direct constructor application doesn't.

    The fact that it is even possible to make this mistake is (as far as I know) just an artifact of poor API design of the network package. Although that has been improving lately, it's quite hard to make API changes to the network package without upsetting some of its many clients.