punchd/punchd.nim

167 lines
5.2 KiB
Nim
Raw Normal View History

2020-07-07 19:39:28 +02:00
import asyncdispatch, asyncnet, os, strformat, strutils
from nativesockets import Domain, SockType, Protocol
from net import IpAddress, Port, `$`
import asyncutils
import message
2020-10-22 00:22:11 +02:00
import tcp_syni_initiator
import tcp_syni_responder
import tcp_nutss_initiator
import tcp_nutss_responder
2020-07-07 19:39:28 +02:00
from strutils import format, join
from nativesockets import setSockOptInt
type
2020-08-22 12:34:12 +02:00
Punchd = ref object
unixSocket: AsyncSocket
2020-10-22 00:22:11 +02:00
tcpSyniInitiator: TcpSyniInitiator
tcpSyniResponder: TcpSyniResponder
tcpNutssInitiator: TcpNutssInitiator
tcpNutssResponder: TcpNutssResponder
2020-08-22 12:34:12 +02:00
Sigint = object of CatchableError
2020-07-07 19:39:28 +02:00
# Requests
2020-10-22 00:22:11 +02:00
InitiateTcpSyni = object
2020-07-07 19:39:28 +02:00
srcIp: IpAddress
2020-08-26 21:33:13 +02:00
srcPorts: seq[Port]
2020-07-07 19:39:28 +02:00
dstIp: IpAddress
2020-08-26 21:33:13 +02:00
dstPorts: seq[Port]
2020-07-07 19:39:28 +02:00
2020-10-22 00:22:11 +02:00
RespondTcpSyni = object
2020-07-07 19:39:28 +02:00
dstIp: IpAddress
2020-08-26 21:33:13 +02:00
dstPorts: seq[Port]
2020-07-07 19:39:28 +02:00
srcIp: IpAddress
2020-08-26 21:33:13 +02:00
srcPorts: seq[Port]
seqNums: seq[uint32]
2020-07-07 19:39:28 +02:00
2020-10-22 00:22:11 +02:00
InitiateTcpNutss = object
srcIp: IpAddress
srcPorts: seq[Port]
dstIp: IpAddress
dstPorts: seq[Port]
2020-10-22 00:22:11 +02:00
RespondTcpNutss = object
dstIp: IpAddress
dstPorts: seq[Port]
srcIp: IpAddress
srcPorts: seq[Port]
2020-10-22 00:22:11 +02:00
extraData: string
const PunchdSocket = "/tmp/punchd.socket"
2020-07-28 00:17:45 +02:00
proc handleSigint() {.noconv.} =
raise newException(Sigint, "received SIGINT")
proc sendToClient(unixSock: AsyncSocket, msg: string,
cmsgs: seq[ControlMessage] = @[]) {.async.} =
if not unixSock.isClosed():
let unixFd = unixSock.getFd.AsyncFD
await unixFd.asyncSendMsg(msg, cmsgs)
2020-08-22 12:34:12 +02:00
proc handleRequest(punchd: Punchd, line: string,
unixSock: AsyncSocket) {.async.} =
2020-07-07 19:39:28 +02:00
var id: string
var sock: AsyncSocket
try:
2020-10-22 00:22:11 +02:00
let args = line.parseArgs(4)
2020-07-07 19:39:28 +02:00
id = args[1]
2020-10-22 00:22:11 +02:00
2020-07-07 19:39:28 +02:00
case args[0]:
2020-10-22 00:22:11 +02:00
of "initiate":
case args[2]:
of "tcp-syni":
let req = parseMessage[InitiateTcpSyni](args[3])
proc progress(seqNumbers: seq[uint32]) {.async.} =
echo "progress! seqNumbers: ", seqNumbers
let content = @["tcp-syni", $req.srcIp, req.srcPorts.join(","),
$req.dstIp, req.dstPorts.join(","),
seqNumbers.join(",")].join("|")
await sendToClient(unixSock, &"progress|{id}|{content}\n")
sock = await punchd.tcpSyniInitiator.initiate(req.srcPorts[0], req.dstIp,
req.dstPorts, progress)
of "tcp-nutss":
let req = parseMessage[InitiateTcpNutss](args[3])
proc progress() {.async.} =
echo "progress!"
let content = @["tcp-nutss", $req.srcIp, req.srcPorts.join(","),
$req.dstIp, req.dstPorts.join(",")].join("|")
await sendToClient(unixSock, &"progress|{id}|{content}\n")
sock = await punchd.tcpNutssInitiator.initiate(req.srcPorts[0], req.dstIp,
req.dstPorts, progress)
else:
raise newException(ValueError, "invalid request")
of "respond":
case args[2]:
of "tcp-syni":
let req = parseMessage[RespondTcpSyni](args[3])
sock = await punchd.tcpSyniResponder.respond(req.srcPorts[0], req.dstIp,
req.dstPorts, req.seqNums)
of "tcp-nutss":
let req = parseMessage[RespondTcpNutss](args[3])
sock = await punchd.tcpNutssResponder.respond(req.srcPorts[0],
req.dstIp, req.dstPorts)
else:
raise newException(ValueError, "invalid request")
2020-07-07 19:39:28 +02:00
else:
raise newException(ValueError, "invalid request")
await sendToClient(unixSock, &"ok|{id}\n", @[fromFd(sock.getFd.AsyncFD)])
2020-10-07 00:31:04 +02:00
sock.close()
2020-07-07 19:39:28 +02:00
except PunchHoleError as e:
await sendToClient(unixSock, &"error|{id}|{e.msg}\n")
2020-07-07 19:39:28 +02:00
except ValueError:
unixSock.close
2020-08-22 12:34:12 +02:00
proc handleRequests(punchd: Punchd, userSock: AsyncSocket) {.async.} =
2020-07-07 19:39:28 +02:00
while true:
if userSock.isClosed:
break
2020-07-07 19:39:28 +02:00
let line = await userSock.recvLine(maxLength = 400)
if line.len == 0:
2020-10-10 11:14:31 +02:00
userSock.close()
2020-07-07 19:39:28 +02:00
break
2020-08-22 12:34:12 +02:00
asyncCheck punchd.handleRequest(line, userSock)
2020-07-07 19:39:28 +02:00
2020-08-22 12:34:12 +02:00
proc handleUsers(punchd: Punchd) {.async.} =
2020-07-07 19:39:28 +02:00
while true:
2020-08-22 12:34:12 +02:00
let user = await punchd.unixSocket.accept()
asyncCheck punchd.handleRequests(user)
2020-07-07 19:39:28 +02:00
proc main() =
2020-07-28 00:17:45 +02:00
setControlCHook(handleSigint)
removeFile(PunchdSocket)
let unixSocket = newAsyncSocket(AF_UNIX, SOCK_STREAM, IPPROTO_IP)
unixSocket.bindUnix(PunchdSocket)
unixSocket.listen()
setFilePermissions(PunchdSocket,
{fpUserRead, fpUserWrite, fpGroupRead, fpGroupWrite,
fpOthersRead, fpOthersWrite})
let punchd = Punchd(unixSocket: unixSocket,
2020-10-22 00:22:11 +02:00
tcpSyniInitiator: initTcpSyniInitiator(),
tcpSyniResponder: initTcpSyniResponder(),
tcpNutssInitiator: initTcpNutssInitiator(),
tcpNutssResponder: initTcpNutssResponder())
2020-08-22 12:34:12 +02:00
asyncCheck handleUsers(punchd)
2020-07-28 00:17:45 +02:00
try:
runForever()
except Sigint:
2020-10-22 00:22:11 +02:00
waitFor punchd.tcpSyniInitiator.cleanup()
waitFor punchd.tcpSyniResponder.cleanup()
waitFor punchd.tcpNutssInitiator.cleanup()
waitFor punchd.tcpNutssResponder.cleanup()
punchd.unixSocket.close()
2020-07-28 00:17:45 +02:00
removeFile(PunchdSocket)
2020-07-07 19:39:28 +02:00
when isMainModule:
main()