feat: INP2P v0.1.0 — complete P2P tunneling system
Core modules (M1-M6): - pkg/protocol: message format, encoding, NAT type enums - pkg/config: server/client config structs, env vars, validation - pkg/auth: CRC64 token, TOTP gen/verify, one-time relay tokens - pkg/nat: UDP/TCP STUN client and server - pkg/signal: WSS message dispatch, sync request/response - pkg/punch: UDP/TCP hole punching + priority chain - pkg/mux: stream multiplexer (7B frame: StreamID+Flags+Len) - pkg/tunnel: mux-based port forwarding with stats - pkg/relay: relay manager with TOTP auth + session bridging - internal/server: signaling server (login/heartbeat/report/coordinator) - internal/client: client (NAT detect/login/punch/relay/reconnect) - cmd/inp2ps + cmd/inp2pc: main entrypoints with graceful shutdown All tests pass: 16 tests across 5 packages Code: 3559 lines core + 861 lines tests = 19 source files
This commit is contained in:
92
pkg/auth/auth.go
Normal file
92
pkg/auth/auth.go
Normal file
@@ -0,0 +1,92 @@
|
||||
// Package auth provides TOTP and token authentication for INP2P.
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"hash/crc64"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// TOTPStep is the time window in seconds for TOTP validity.
|
||||
// A code is valid for ±1 step to allow for clock drift.
|
||||
TOTPStep int64 = 60
|
||||
)
|
||||
|
||||
var crcTable = crc64.MakeTable(crc64.ECMA)
|
||||
|
||||
// MakeToken generates a token from user+password using CRC64.
|
||||
func MakeToken(user, password string) uint64 {
|
||||
return crc64.Checksum([]byte(user+password), crcTable)
|
||||
}
|
||||
|
||||
// GenTOTP generates a TOTP code for relay authentication.
|
||||
func GenTOTP(token uint64, ts int64) uint64 {
|
||||
step := ts / TOTPStep
|
||||
buf := make([]byte, 16)
|
||||
binary.BigEndian.PutUint64(buf[:8], token)
|
||||
binary.BigEndian.PutUint64(buf[8:], uint64(step))
|
||||
|
||||
mac := hmac.New(sha256.New, buf[:8])
|
||||
mac.Write(buf[8:])
|
||||
sum := mac.Sum(nil)
|
||||
|
||||
return binary.BigEndian.Uint64(sum[:8])
|
||||
}
|
||||
|
||||
// VerifyTOTP verifies a TOTP code with ±1 step tolerance.
|
||||
func VerifyTOTP(code uint64, token uint64, ts int64) bool {
|
||||
for delta := int64(-1); delta <= 1; delta++ {
|
||||
expected := GenTOTP(token, ts+delta*TOTPStep)
|
||||
if code == expected {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RelayToken generates a one-time relay token signed by the server.
|
||||
// Used for cross-user super relay authentication.
|
||||
type RelayToken struct {
|
||||
SessionID string `json:"sessionID"`
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
Relay string `json:"relay"`
|
||||
Expires int64 `json:"expires"`
|
||||
Signature []byte `json:"signature"`
|
||||
}
|
||||
|
||||
// SignRelayToken creates a signed one-time relay token.
|
||||
func SignRelayToken(secret []byte, sessionID, from, to, relay string, ttl time.Duration) RelayToken {
|
||||
rt := RelayToken{
|
||||
SessionID: sessionID,
|
||||
From: from,
|
||||
To: to,
|
||||
Relay: relay,
|
||||
Expires: time.Now().Add(ttl).Unix(),
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("%s:%s:%s:%s:%d", rt.SessionID, rt.From, rt.To, rt.Relay, rt.Expires)
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
mac.Write([]byte(msg))
|
||||
rt.Signature = mac.Sum(nil)
|
||||
|
||||
return rt
|
||||
}
|
||||
|
||||
// VerifyRelayToken validates a signed relay token.
|
||||
func VerifyRelayToken(secret []byte, rt RelayToken) bool {
|
||||
if time.Now().Unix() > rt.Expires {
|
||||
return false
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("%s:%s:%s:%s:%d", rt.SessionID, rt.From, rt.To, rt.Relay, rt.Expires)
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
mac.Write([]byte(msg))
|
||||
expected := mac.Sum(nil)
|
||||
|
||||
return hmac.Equal(rt.Signature, expected)
|
||||
}
|
||||
Reference in New Issue
Block a user