predict dst ports while accepting too; inject low-TTL SYN instead of using connect
This commit is contained in:
parent
4cf608459f
commit
37f02bc2ba
50
tcp_syni.nim
50
tcp_syni.nim
|
@ -225,22 +225,6 @@ proc connect*(puncher: TcpSyniPuncher, srcPort: Port, dstIp: IpAddress,
|
|||
except OSError as e:
|
||||
raise newException(PunchHoleError, e.msg)
|
||||
|
||||
proc prepareAccept(attempt: AcceptAttempt) {.async.} =
|
||||
for dstPort in attempt.dstPorts:
|
||||
var sock: AsyncSocket
|
||||
try:
|
||||
sock = newAsyncSocket()
|
||||
sock.setSockOpt(OptReuseAddr, true)
|
||||
sock.getFd.setSockOptInt(IPPROTO_IP, IP_TTL, 2)
|
||||
sock.bindAddr(attempt.srcPort, $(attempt.srcIp))
|
||||
let connectFuture = sock.connect($(attempt.dstIp), dstPort)
|
||||
await connectFuture or sleepAsync(Timeout)
|
||||
if connectFuture.finished():
|
||||
echo "connected during accept phase"
|
||||
except OSError:
|
||||
discard
|
||||
sock.close()
|
||||
|
||||
proc doAccept(puncher: TcpSyniPuncher, srcIp: IpAddress,
|
||||
srcPort: Port) {.async.} =
|
||||
let sock = newAsyncSocket()
|
||||
|
@ -281,24 +265,30 @@ proc accept*(puncher: TcpSyniPuncher, srcPort: Port, dstIp: IpAddress,
|
|||
if a.dstIp == dstIp and
|
||||
a.dstPorts.any(proc (p: Port): bool = p in dstPorts):
|
||||
raise newException(PunchHoleError, "hole punching for given parameters already active")
|
||||
let attempt = AcceptAttempt(srcIp: localIp, srcPort: srcPort, dstIp: dstIp,
|
||||
dstPorts: dstPorts, seqNums: seqNums,
|
||||
future: newFuture[AsyncSocket]("accept"))
|
||||
puncher.acceptAttempts.add(attempt)
|
||||
await attempt.addFirewallRules()
|
||||
await attempt.prepareAccept()
|
||||
try:
|
||||
let rawFd = setupTcpInjectingSocket()
|
||||
let attempt = AcceptAttempt(srcIp: localIp, srcPort: srcPort, dstIp: dstIp,
|
||||
dstPorts: predictPortRange(dstPorts),
|
||||
seqNums: seqNums,
|
||||
future: newFuture[AsyncSocket]("accept"))
|
||||
puncher.acceptAttempts.add(attempt)
|
||||
await attempt.addFirewallRules()
|
||||
for dstPort in attempt.dstPorts:
|
||||
let synOut = IpPacket(protocol: tcp, ipAddrSrc: attempt.srcIp,
|
||||
ipAddrDst: attempt.dstIp, ipTTL: 2,
|
||||
tcpPortSrc: attempt.srcPort, tcpPortDst: dstPort,
|
||||
tcpSeqNumber: 0, tcpAckNumber: 0, tcpFlags: {SYN},
|
||||
tcpWindowSize: 1452 * 10)
|
||||
await rawFd.injectTcpPacket(synOut)
|
||||
for seqNum in attempt.seqNums:
|
||||
let ipPacket = IpPacket(protocol: tcp, ipAddrSrc: attempt.dstIp,
|
||||
ipAddrDst: attempt.srcIp, ipTTL: 64,
|
||||
tcpPortSrc: dstPort,
|
||||
tcpPortDst: attempt.srcPort,
|
||||
tcpSeqNumber: seqNum, tcpAckNumber: 0,
|
||||
tcpFlags: {SYN}, tcpWindowSize: 1452 * 10)
|
||||
echo &"[{ipPacket.ipAddrSrc}:{ipPacket.tcpPortSrc} -> {ipPacket.ipAddrDst}:{ipPacket.tcpPortDst}, SEQ {ipPacket.tcpSeqNumber}] injecting SYN"
|
||||
await rawFd.injectTcpPacket(ipPacket)
|
||||
let synIn = IpPacket(protocol: tcp, ipAddrSrc: attempt.dstIp,
|
||||
ipAddrDst: attempt.srcIp, ipTTL: 64,
|
||||
tcpPortSrc: dstPort,
|
||||
tcpPortDst: attempt.srcPort,
|
||||
tcpSeqNumber: seqNum, tcpAckNumber: 0,
|
||||
tcpFlags: {SYN}, tcpWindowSize: 1452 * 10)
|
||||
echo &"[{synIn.ipAddrSrc}:{synIn.tcpPortSrc} -> {synIn.ipAddrDst}:{synIn.tcpPortDst}, SEQ {synIn.tcpSeqNumber}] injecting SYN"
|
||||
await rawFd.injectTcpPacket(synIn)
|
||||
closeSocket(rawFd)
|
||||
await attempt.future or sleepAsync(Timeout)
|
||||
await attempt.deleteFirewallRules()
|
||||
|
|
Loading…
Reference in New Issue