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:
2026-03-02 15:13:22 +08:00
commit 91e3d4da2a
23 changed files with 4681 additions and 0 deletions

92
pkg/auth/auth.go Normal file
View 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)
}