{-# LANGUAGE OverloadedStrings #-} {- | Module : Main License : BSD-style Copyright : (c) 2010-2019 Vincent Hanquez Stability : experimental Portability : unknown An example application. -} module Main ( main ) where import Data.ByteString.Char8 ( pack ) import Network.BSD ( getHostByName, hostAddresses ) import Network.Socket ( Family (..), SockAddr (..), SocketType (..), close , defaultProtocol ) import qualified Network.Socket as Network import Network.Socket.ByteString ( recv, sendAll ) import Network.Socks5 ( SocksAddress (..), SocksHostAddress (..), defaultSocksConf , socksConnect, socksConnectName ) import System.Environment ( getArgs ) main :: IO () main = do args <- getArgs let serverName = "localhost" serverPort = 1080 destinationName = case args of [] -> "www.google.com" (x:_) -> x -- A SOCKS server is expected to be running on localhost port 1080. he <- getHostByName serverName case hostAddresses he of [] -> putStrLn "Error: expected a host address." (ha:_) -> do let socksServerAddr = SockAddrInet serverPort ha example1 socksServerAddr destinationName example2 socksServerAddr destinationName where -- Connect to @destName on port 80 through the SOCKS server. www.google.com -- gets resolved on the client here and then the sockaddr is passed to -- socksConnectAddr. example1 socksServerAddr destName = do (socket, _) <- socksConnect (defaultSocksConf socksServerAddr) (SocksAddress (SocksAddrDomainName $ pack destName) 80) sendAll socket "GET / HTTP/1.0\r\n\r\n" recv socket 4096 >>= print close socket -- Connect to @destName on port 80 through the SOCKS server. The server is -- doing the resolution itself. example2 socksServerAddr destName = do socket <- Network.socket AF_INET Stream defaultProtocol socksConnectName socket (defaultSocksConf socksServerAddr) destName 80 sendAll socket "GET / HTTP/1.0\r\n\r\n" recv socket 4096 >>= print close socket