{-# LANGUAGE OverloadedStrings #-} import Network.Socks5 import Network.Socket hiding (recv) import Network.Socket.ByteString import Network.BSD import Network import Data.ByteString.Char8 () import qualified Data.ByteString.Char8 as BC import System.IO (hClose, hFlush) import System.Environment (getArgs) main = do args <- getArgs let serverName = "localhost" let serverPort = 1080 let destinationName = case args of [] -> "www.google.com" (x:_) -> x -- socks server is expected to be running on localhost port 1080 he <- getHostByName serverName let socksServerAddr = SockAddrInet serverPort (head $ hostAddresses he) example1 socksServerAddr destinationName example2 socksServerAddr destinationName example3 serverName serverPort destinationName 80 where -- connect to @destName on port 80 through the socks server -- www.google.com get resolve on the client here and then the sockaddr is -- passed to socksConnectAddr example1 socksServerAddr destName = do socket <- socket AF_INET Stream defaultProtocol gHost <- getHostByName destName let destinationAddr = SockAddrInet 80 (head $ hostAddresses gHost) socksConnectAddr socket socksServerAddr destinationAddr sendAll socket "GET / HTTP/1.0\r\n\r\n" recv socket 4096 >>= putStrLn . show sClose socket -- connect to @destName on port 80 through the socks server -- the server is doing the resolution itself example2 socksServerAddr destName = do socket <- socket AF_INET Stream defaultProtocol socksConnectName socket socksServerAddr destName 80 sendAll socket "GET / HTTP/1.0\r\n\r\n" recv socket 4096 >>= putStrLn . show sClose socket example3 sname sport dname dport = do handle <- socksConnectTo sname (PortNumber sport) dname (PortNumber dport) BC.hPut handle "GET / HTTP/1.0\r\n\r\n" hFlush handle BC.hGet handle 1024 >>= putStrLn . show hClose handle