"/run/tproxy/socket"
do
hSetBuffering stdout NoBuffering
-- 1. Get the configuration file path
args <- getArgs
let configFile = case args of
(f:_) -> f
[] -> "servers.yaml"
-- 2. Call the exported function from the ConfigParser module
parseResult <- ConfigParser.parseConfigFile configFile
case parseResult of
-- Handle failure (The Left String contains the formatted error)
Left errorMessage -> do
hPutStrLn stderr errorMessage
-- Handle success
Right cfg -> do
putStrLn $ "Successfully loaded configuration from " ++ configFile ++ ":"
-- Accessing the first entry's nameserver
case cfg of
(entry:_) -> do
putStrLn $ "First server " ++ show (name entry)
ip <- waitForIP (T.unpack $ nameserver entry) (T.unpack $ domain entry)
let raw = fromMaybe ICMP (textToRawMode $ raw_mode entry)
let pwd = T.unpack $ udp2raw_password entry
writeEnv ip pwd raw
start ip
-- Clean up old socket if exists
catch (removeFile socketPath) (\(_::SomeException) -> pure ())
sock <- socket AF_UNIX Stream 0
bind sock (SockAddrUnix socketPath)
setFileMode socketPath 0o775
listen sock 1
forever $ do
(conn, _) <- accept sock
_ <- forkIO $ (handleClient conn ip)
pure ()
[] -> putStrLn "Configuration file was empty."
do
h <- socketToHandle conn ReadWriteMode
hSetBuffering h LineBuffering
cmd <- hGetLine h
case cmd of
"start" -> do
putStrLn "Received start command"
start ip
hPutStrLn h "started"
"stop" -> do
putStrLn "Received stop command"
stop ip
hPutStrLn h "stopped"
"exit" -> do
putStrLn "Exiting tproxy service"
hPutStrLn h "bye"
stop ip
hClose h
exitSuccess
_ -> hPutStrLn h "unknown command"
hClose h
do
applyRules
applyICMP ip
do
clearRules
clearICMP ip