init commit
This commit is contained in:
215
cmd/extract/main.go
Normal file
215
cmd/extract/main.go
Normal file
@@ -0,0 +1,215 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type LogEntry struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Protocol string `json:"protocol"`
|
||||
Type string `json:"type"`
|
||||
Summary string `json:"summary"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Hardcode for reliability
|
||||
logFile := "session_20260107_174406.jsonl"
|
||||
|
||||
if logFile == "" {
|
||||
panic("No session log found")
|
||||
}
|
||||
|
||||
fmt.Printf("Reading %s...\n", logFile)
|
||||
f, err := os.Open(logFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
// Larger buffer for huge lines
|
||||
buf := make([]byte, 1024*1024)
|
||||
scanner.Buffer(buf, 1024*1024)
|
||||
|
||||
for scanner.Scan() {
|
||||
var entry LogEntry
|
||||
if err := json.Unmarshal(scanner.Bytes(), &entry); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Looking for the huge packet
|
||||
// Summary: "Packet 1 | Req 256 | Len 24182" (or similar length)
|
||||
if entry.Protocol == "TCP" && strings.Contains(entry.Summary, "Len") {
|
||||
// Check if Data has hex
|
||||
dataMap, ok := entry.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
hexData, ok := dataMap["hex"].(string)
|
||||
if !ok || len(hexData) < 20000 { // Look for huge payload
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Println("Found candidate packet:", entry.Summary)
|
||||
packetBytes, err := hex.DecodeString(hexData)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Parse wrapper
|
||||
// We assume the payload of the wrapper is the Message
|
||||
// Wrapper: [Tag1:PacketID] [Tag3:MessageBytes]
|
||||
// We want MessageBytes.
|
||||
// Simple parser: skip Tag1/Val1. Find Tag3 (0x1a).
|
||||
// 08 02 (Packet ID 2) -> 2 bytes.
|
||||
// 1a (Tag 3) -> 1 byte.
|
||||
// Length (Varint).
|
||||
|
||||
// Heuristic search for 1a and length
|
||||
// Or simple protobuf reader
|
||||
r := bytes.NewReader(packetBytes)
|
||||
// Skip Field 1 (08 xx)
|
||||
b, _ := r.ReadByte()
|
||||
if b == 0x08 {
|
||||
// Read varint
|
||||
for {
|
||||
b, _ := r.ReadByte()
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Might be diff packet ID? Log said Packet 1. 08 01.
|
||||
fmt.Println("Warning: Expected 0x08 tag, got", b)
|
||||
// Reset and try to find 0x1a anyway
|
||||
r.Seek(0, 0)
|
||||
}
|
||||
|
||||
// Read Tag
|
||||
for {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if b == 0x1a { // Field 3
|
||||
// This is likely the payload
|
||||
fmt.Println("Found Field 3 tag (Message Payload)")
|
||||
|
||||
// Decode length
|
||||
lenVal := uint64(0)
|
||||
shift := uint(0)
|
||||
for {
|
||||
b, _ := r.ReadByte()
|
||||
lenVal |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
shift += 7
|
||||
}
|
||||
fmt.Printf("Payload Length: %d\n", lenVal)
|
||||
|
||||
payload := make([]byte, lenVal)
|
||||
n, _ := r.Read(payload)
|
||||
if uint64(n) != lenVal {
|
||||
fmt.Println("Warning: Short read")
|
||||
}
|
||||
|
||||
// Now we have the Message (RequestNumber + GameStatusReportRequest).
|
||||
// RequestNumber is Field 1 (08 80 04 -> 512).
|
||||
// GameStatusReportRequest is Field 512 (Tag 82 20 -> 1002).
|
||||
// We need the value of Field 512.
|
||||
|
||||
r2 := bytes.NewReader(payload)
|
||||
|
||||
for {
|
||||
tag, err := readVarint(r2)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fieldNum := tag >> 3
|
||||
wireType := tag & 7
|
||||
|
||||
if fieldNum == 512 {
|
||||
fmt.Println("Found Field 512 (GameStatusReportRequest)")
|
||||
// Read length
|
||||
msgLen, _ := readVarint(r2)
|
||||
msgBytes := make([]byte, msgLen)
|
||||
r2.Read(msgBytes)
|
||||
|
||||
// msgBytes is GameStatusReportRequest.
|
||||
// It contains status_report (Field 1).
|
||||
// We want to save *msgBytes* so we can inject it into a new Message struct?
|
||||
// Or extract StatusReport payload?
|
||||
|
||||
// The user wants to set GameStatusReportRequest.StatusReport.
|
||||
// So check inside msgBytes for Field 1.
|
||||
r3 := bytes.NewReader(msgBytes)
|
||||
tag3, _ := readVarint(r3)
|
||||
if (tag3 >> 3) == 1 {
|
||||
fmt.Println("Found Field 1 (StatusReport)")
|
||||
srLen, _ := readVarint(r3)
|
||||
srBytes := make([]byte, srLen)
|
||||
r3.Read(srBytes)
|
||||
|
||||
// Wait, is StatusReport just one field?
|
||||
// The log showed StatusReport had GameID, Status, Players...
|
||||
// Ah, GameStatusReportRequest message only has ONE field: `status_report`.
|
||||
// So `msgBytes` is the wire bytes for `GameStatusReportRequest`.
|
||||
// If we assume `main.go` has `GameStatusReportRequest` struct, we can unmarshal `msgBytes` into it.
|
||||
// YES.
|
||||
|
||||
err = ioutil.WriteFile("mock_gamestatus.bin", msgBytes, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Saved mock_gamestatus.bin")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Skip
|
||||
skip(r2, wireType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readVarint(r *bytes.Reader) (uint64, error) {
|
||||
x := uint64(0)
|
||||
s := uint(0)
|
||||
for {
|
||||
b, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
x |= uint64(b&0x7F) << s
|
||||
if b < 0x80 {
|
||||
return x, nil
|
||||
}
|
||||
s += 7
|
||||
}
|
||||
}
|
||||
|
||||
func skip(r *bytes.Reader, wireType uint64) {
|
||||
switch wireType {
|
||||
case 0:
|
||||
readVarint(r)
|
||||
case 1:
|
||||
r.Seek(8, 1)
|
||||
case 2:
|
||||
l, _ := readVarint(r)
|
||||
r.Seek(int64(l), 1)
|
||||
case 5:
|
||||
r.Seek(4, 1)
|
||||
}
|
||||
}
|
||||
441
cmd/proxy/main.go
Normal file
441
cmd/proxy/main.go
Normal file
@@ -0,0 +1,441 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Config
|
||||
var (
|
||||
TargetHTTPHost = "https://api.asmodee.net"
|
||||
TargetTCPHost = "got.games.asmodee.net"
|
||||
TargetTCPPort = "2445"
|
||||
ProxyHTTPPort = ":8080"
|
||||
ProxyTCPPort = ":3000"
|
||||
LogFileName = ""
|
||||
LogFile *os.File
|
||||
LogMutex sync.Mutex
|
||||
)
|
||||
|
||||
// Log Entry Structure
|
||||
type LogEntry struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Protocol string `json:"protocol"` // HTTP or TCP
|
||||
Type string `json:"type"` // REQUEST or RESPONSE
|
||||
Summary string `json:"summary"` // e.g. "GET /v1/foo" or "Packet 123"
|
||||
Data interface{} `json:"data"` // Structured data or raw info
|
||||
}
|
||||
|
||||
// Write to JSONL
|
||||
func logJSON(entry LogEntry) {
|
||||
entry.Timestamp = time.Now().Format(time.RFC3339Nano)
|
||||
LogMutex.Lock()
|
||||
defer LogMutex.Unlock()
|
||||
|
||||
bytes, err := json.Marshal(entry)
|
||||
if err == nil {
|
||||
if LogFile != nil {
|
||||
LogFile.Write(bytes)
|
||||
LogFile.WriteString("\n")
|
||||
} else {
|
||||
fmt.Println(string(bytes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&TargetHTTPHost, "target-http", "https://api.asmodee.net", "Target HTTP Host")
|
||||
flag.StringVar(&TargetTCPHost, "target-tcp-host", "got.games.asmodee.net", "Target TCP Host")
|
||||
flag.StringVar(&TargetTCPPort, "target-tcp-port", "2445", "Target TCP Port")
|
||||
flag.Parse()
|
||||
|
||||
LogFileName = fmt.Sprintf("session_%s.jsonl", time.Now().Format("20060102_150405"))
|
||||
f, err := os.Create(LogFileName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
LogFile = f
|
||||
defer LogFile.Close()
|
||||
|
||||
fmt.Printf("Starting Proxy...\nLog: %s\nHTTP Target: %s\nTCP Target Default: %s:%s\n", LogFileName, TargetHTTPHost, TargetTCPHost, TargetTCPPort)
|
||||
|
||||
// Start HTTP Proxy
|
||||
go startHTTPProxy()
|
||||
|
||||
// Start TCP Proxy
|
||||
startTCPProxy()
|
||||
}
|
||||
|
||||
// --- HTTP Proxy ---
|
||||
|
||||
func startHTTPProxy() {
|
||||
http.HandleFunc("/", handleHTTPRequest)
|
||||
fmt.Println("[HTTP] Listening on " + ProxyHTTPPort)
|
||||
log.Fatal(http.ListenAndServe(ProxyHTTPPort, nil))
|
||||
}
|
||||
|
||||
func handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// Log Request
|
||||
bodyBytes, _ := ioutil.ReadAll(r.Body)
|
||||
r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) // Restore for forwarding
|
||||
|
||||
logJSON(LogEntry{
|
||||
Protocol: "HTTP",
|
||||
Type: "REQUEST",
|
||||
Summary: fmt.Sprintf("%s %s", r.Method, r.URL.Path),
|
||||
Data: map[string]interface{}{
|
||||
"headers": r.Header,
|
||||
"body": string(bodyBytes),
|
||||
},
|
||||
})
|
||||
|
||||
// Forward Request
|
||||
targetURL := TargetHTTPHost + r.URL.Path
|
||||
if r.URL.RawQuery != "" {
|
||||
targetURL += "?" + r.URL.RawQuery
|
||||
}
|
||||
|
||||
proxyReq, err := http.NewRequest(r.Method, targetURL, bytes.NewBuffer(bodyBytes))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
// Copy headers
|
||||
for name, values := range r.Header {
|
||||
for _, value := range values {
|
||||
proxyReq.Header.Add(name, value)
|
||||
}
|
||||
}
|
||||
// Remove Hop-by-hop headers
|
||||
proxyReq.Header.Del("Host") // Let http client set it
|
||||
// Might need to set Host header manually if target expects it
|
||||
// proxyReq.Host = ...
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(proxyReq)
|
||||
if err != nil {
|
||||
// Log Error
|
||||
logJSON(LogEntry{
|
||||
Protocol: "HTTP",
|
||||
Type: "ERROR",
|
||||
Summary: "Forwarding Failed",
|
||||
Data: err.Error(),
|
||||
})
|
||||
http.Error(w, err.Error(), http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, _ := ioutil.ReadAll(resp.Body)
|
||||
|
||||
// Log Response
|
||||
logJSON(LogEntry{
|
||||
Protocol: "HTTP",
|
||||
Type: "RESPONSE",
|
||||
Summary: fmt.Sprintf("%s %d", r.URL.Path, resp.StatusCode),
|
||||
Data: map[string]interface{}{
|
||||
"status": resp.StatusCode,
|
||||
"headers": resp.Header,
|
||||
"body": string(respBody),
|
||||
},
|
||||
})
|
||||
|
||||
// Sniff for TCP Info
|
||||
// Look for "server": { "host": ... } or "HostName": ...
|
||||
sniffTCPInfo(respBody)
|
||||
|
||||
// Write Response
|
||||
for name, values := range resp.Header {
|
||||
for _, value := range values {
|
||||
w.Header().Add(name, value)
|
||||
}
|
||||
}
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
w.Write(respBody)
|
||||
}
|
||||
|
||||
func sniffTCPInfo(body []byte) {
|
||||
// Search for "host":"..." and "port":... pattern
|
||||
s := string(body)
|
||||
if strings.Contains(s, "\"host\"") && strings.Contains(s, "\"port\"") {
|
||||
idxHost := strings.Index(s, "\"host\"")
|
||||
if idxHost != -1 {
|
||||
// Find value
|
||||
startQuote := strings.Index(s[idxHost:], ":") + idxHost + 1
|
||||
startQuote = strings.Index(s[startQuote:], "\"") + startQuote
|
||||
endQuote := strings.Index(s[startQuote+1:], "\"") + startQuote + 1
|
||||
|
||||
if startQuote != -1 && endQuote != -1 {
|
||||
extractedHost := s[startQuote+1 : endQuote]
|
||||
if extractedHost != "" {
|
||||
fmt.Printf("[PROXY] Sniffed TCP Host: %s\n", extractedHost)
|
||||
TargetTCPHost = extractedHost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idxPort := strings.Index(s, "\"port\"")
|
||||
if idxPort != -1 {
|
||||
// Find value (number)
|
||||
colon := strings.Index(s[idxPort:], ":") + idxPort
|
||||
// Find first digit after colon
|
||||
startNum := -1
|
||||
endNum := -1
|
||||
for i := colon + 1; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c >= '0' && c <= '9' {
|
||||
if startNum == -1 {
|
||||
startNum = i
|
||||
}
|
||||
} else if startNum != -1 {
|
||||
// End of number
|
||||
endNum = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if startNum != -1 {
|
||||
if endNum == -1 {
|
||||
endNum = len(s)
|
||||
}
|
||||
extractedPort := s[startNum:endNum]
|
||||
fmt.Printf("[PROXY] Sniffed TCP Port: %s\n", extractedPort)
|
||||
TargetTCPPort = extractedPort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func findHostPortRecursive(obj interface{}) {
|
||||
switch v := obj.(type) {
|
||||
case map[string]interface{}:
|
||||
if h, ok := v["host"].(string); ok {
|
||||
TargetTCPHost = h
|
||||
fmt.Printf("[PROXY] Sniffed TCP Host: %s\n", h)
|
||||
}
|
||||
if p, ok := v["port"].(float64); ok { // JSON numbers are float64 in generic interface
|
||||
TargetTCPPort = fmt.Sprintf("%d", int(p))
|
||||
fmt.Printf("[PROXY] Sniffed TCP Port: %s\n", TargetTCPPort)
|
||||
}
|
||||
for _, val := range v {
|
||||
findHostPortRecursive(val)
|
||||
}
|
||||
case []interface{}:
|
||||
for _, val := range v {
|
||||
findHostPortRecursive(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- TCP Proxy ---
|
||||
|
||||
func startTCPProxy() {
|
||||
cert, err := generateSelfSignedCert()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
listener, err := tls.Listen("tcp", ProxyTCPPort, cert)
|
||||
if err != nil {
|
||||
log.Fatalf("TCP Listen failed: %v", err)
|
||||
}
|
||||
fmt.Println("[TCP] Listening on " + ProxyTCPPort)
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
log.Println("TCP Accept error:", err)
|
||||
continue
|
||||
}
|
||||
go handleTCPConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleTCPConn(clientConn net.Conn) {
|
||||
defer clientConn.Close()
|
||||
|
||||
// Connect to Real Server
|
||||
targetAddr := fmt.Sprintf("%s:%s", TargetTCPHost, TargetTCPPort)
|
||||
fmt.Printf("[TCP] New Connection. Forwarding to %s\n", targetAddr)
|
||||
|
||||
// Use TLS to connect to Real Server
|
||||
serverConn, err := tls.Dial("tcp", targetAddr, &tls.Config{
|
||||
InsecureSkipVerify: true, // We assume official server cert is fine but we skip verify to avoid setup
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Failed to dial target %s: %v\n", targetAddr, err)
|
||||
return
|
||||
}
|
||||
defer serverConn.Close()
|
||||
|
||||
// Pipe
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
// Client -> Server
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
interceptAndLogTCP(clientConn, serverConn, "CLIENT->SERVER")
|
||||
}()
|
||||
|
||||
// Server -> Client
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
interceptAndLogTCP(serverConn, clientConn, "SERVER->CLIENT")
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func interceptAndLogTCP(src, dst net.Conn, direction string) {
|
||||
// We need to parse frames to log them effectively?
|
||||
// The protocol is: 4 bytes length + Payload.
|
||||
// Payload: Varint PacketID, Varint RequestID, Payload.
|
||||
|
||||
// We will try to read in a buffer loop, parse length prefix, log, then forward.
|
||||
// But simply copying stream `io.Copy` is safer for latency.
|
||||
// However, we want to LOG. So we MUST read packet by packet.
|
||||
|
||||
header := make([]byte, 4)
|
||||
for {
|
||||
// Read Head
|
||||
_, err := io.ReadFull(src, header)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
length := binary.BigEndian.Uint32(header)
|
||||
|
||||
// Read Body
|
||||
body := make([]byte, length)
|
||||
_, err = io.ReadFull(src, body)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
// Write to Dst
|
||||
// Write header + body
|
||||
dst.Write(header)
|
||||
dst.Write(body)
|
||||
|
||||
// Log
|
||||
parseAndLogPacket(direction, body)
|
||||
}
|
||||
}
|
||||
|
||||
func parseAndLogPacket(direction string, data []byte) {
|
||||
// Basic Decode of Packet Wrapper
|
||||
// Packet ID (Field 1, Varint)
|
||||
// Payload (Field 3, Bytes) -> Message
|
||||
|
||||
r := bytes.NewReader(data)
|
||||
|
||||
packetID := int64(-1)
|
||||
var payloadBytes []byte
|
||||
|
||||
for {
|
||||
tag, err := binary.ReadUvarint(r)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fieldNum := tag >> 3
|
||||
wireType := tag & 7
|
||||
|
||||
if fieldNum == 1 && wireType == 0 {
|
||||
packetID, _ = binary.ReadVarint(r) // ReadVarint for int64
|
||||
} else if fieldNum == 3 && wireType == 2 {
|
||||
l, _ := binary.ReadUvarint(r)
|
||||
payloadBytes = make([]byte, l)
|
||||
r.Read(payloadBytes)
|
||||
} else {
|
||||
// Skip
|
||||
skip(r, wireType)
|
||||
}
|
||||
}
|
||||
|
||||
// If we found payload, parse Message
|
||||
requestID := int64(-1)
|
||||
if payloadBytes != nil {
|
||||
pr := bytes.NewReader(payloadBytes)
|
||||
for {
|
||||
tag, err := binary.ReadUvarint(pr)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fieldNum := tag >> 3
|
||||
wireType := tag & 7
|
||||
|
||||
if fieldNum == 1 && wireType == 0 { // Message.request_number
|
||||
requestID, _ = binary.ReadVarint(pr)
|
||||
} else {
|
||||
skip(pr, wireType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logJSON(LogEntry{
|
||||
Protocol: "TCP",
|
||||
Type: direction,
|
||||
Summary: fmt.Sprintf("Packet %d | Req %d | Len %d", packetID, requestID, len(data)),
|
||||
Data: map[string]interface{}{
|
||||
"packet_id": packetID,
|
||||
"request_id": requestID,
|
||||
"hex": hex.EncodeToString(data),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func skip(r *bytes.Reader, wireType uint64) {
|
||||
switch wireType {
|
||||
case 0:
|
||||
binary.ReadUvarint(r)
|
||||
case 1:
|
||||
r.Seek(8, io.SeekCurrent)
|
||||
case 2:
|
||||
l, _ := binary.ReadUvarint(r)
|
||||
r.Seek(int64(l), io.SeekCurrent)
|
||||
case 5:
|
||||
r.Seek(4, io.SeekCurrent)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Cert Gen (Copied) ---
|
||||
func generateSelfSignedCert() (*tls.Config, error) {
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
template := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{Organization: []string{"Proxy"}},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour * 24),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
|
||||
DNSNames: []string{"localhost"},
|
||||
}
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tls.Config{Certificates: []tls.Certificate{{Certificate: [][]byte{derBytes}, PrivateKey: priv}}}, nil
|
||||
}
|
||||
24
cmd/server/main.go
Normal file
24
cmd/server/main.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"customServer/internal/network"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// The state manager initializes itself via init() in internal/state
|
||||
|
||||
// 1. HTTP Server for REST API (Port 8080)
|
||||
go func() {
|
||||
if err := network.StartHTTPServer(":8080"); err != nil {
|
||||
log.Fatalf("HTTP server failed: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 2. TCP Server for Scalable Server (Port 3000) with SSL
|
||||
fmt.Println("[Main] Starting TCP Server...")
|
||||
if err := network.StartTCPServer(":3000"); err != nil {
|
||||
log.Fatalf("TCP server failed: %v", err)
|
||||
}
|
||||
}
|
||||
1022
cmd/server/main.go.bak
Normal file
1022
cmd/server/main.go.bak
Normal file
File diff suppressed because it is too large
Load Diff
1
cmd/server/mock_gamedata.b64
Normal file
1
cmd/server/mock_gamedata.b64
Normal file
@@ -0,0 +1 @@
|
||||
CICggOjD6dXeNxAKGAMiVnsibmFtZSI6InN3dCIsInZhbHVlIjp7InNsbiI6eyJlaWQiOjE5MiwidHJzIjpbeyJlbHQiOls2NTNdLCJuYW1lIjoiZWx0ciJ9XX0sImN0ciI6MX19IlZ7Im5hbWUiOiJzd3QiLCJ2YWx1ZSI6eyJzbG4iOnsiZWlkIjo2NTMsInRycyI6W3siZWx0IjpbNTUxXSwibmFtZSI6ImVsdHIifV19LCJjdHIiOjF9fSJWeyJuYW1lIjoic3d0IiwidmFsdWUiOnsic2xuIjp7ImVpZCI6MjAyLCJ0cnMiOlt7ImVsdCI6WzYzOV0sIm5hbWUiOiJlbHRyIn1dfSwiY3RyIjoxfX0iVnsibmFtZSI6InN3dCIsInZhbHVlIjp7InNsbiI6eyJlaWQiOjYzOSwidHJzIjpbeyJlbHQiOls1NTFdLCJuYW1lIjoiZWx0ciJ9XX0sImN0ciI6MX19IlZ7Im5hbWUiOiJzd3QiLCJ2YWx1ZSI6eyJzbG4iOnsiZWlkIjoyMDIsInRycyI6W3siZWx0IjpbNjM5XSwibmFtZSI6ImVsdHIifV19LCJjdHIiOjF9fSJWeyJuYW1lIjoic3d0IiwidmFsdWUiOnsic2xuIjp7ImVpZCI6MTkyLCJ0cnMiOlt7ImVsdCI6WzY2MV0sIm5hbWUiOiJlbHRyIn1dfSwiY3RyIjoxfX0iVnsibmFtZSI6InN3dCIsInZhbHVlIjp7InNsbiI6eyJlaWQiOjE5MCwidHJzIjpbeyJlbHQiOls2NjNdLCJuYW1lIjoiZWx0ciJ9XX0sImN0ciI6MX19IlZ7Im5hbWUiOiJzd3QiLCJ2YWx1ZSI6eyJzbG4iOnsiZWlkIjo2NjMsInRycyI6W3siZWx0IjpbNTUxXSwibmFtZSI6ImVsdHIifV19LCJjdHIiOjF9fSJWeyJuYW1lIjoic3d0IiwidmFsdWUiOnsic2xuIjp7ImVpZCI6MTkwLCJ0cnMiOlt7ImVsdCI6WzY0NV0sIm5hbWUiOiJlbHRyIn1dfSwiY3RyIjoxfX0iIHsibmFtZSI6InN3dCIsInZhbHVlIjp7InNsbiI6eyJlaWQiOjE5MiwidHJzIjpbeyJlbHQiOltdLCJuYW1lIjoiZWx0ciJ9XX0sImN0ciI6NTd9fSJXeyJuYW1lIjoic3d0IiwidmFsdWUiOnsic2xuIjp7ImVpZCI6MTc1LCJ0cnMiOlt7ImVsdCI6WzE2N10sIm5hbWUiOiJlbHRyIn1dfSwiY3RyIjo2MX19IlR7Im5hbWUiOiJzd3QiLCJ2YWx1ZSI6eyJzbG4iOnsiZWlkIjoxNjksInRycyI6W3siZWx0IjpbXSwibmFtZSI6ImVsdHIifV19LCJjdHIiOjYzfX0iV3sibmFtZSI6InN3dCIsInZhbHVlIjp7InNsbiI6eyJlaWQiOjI1MCwidHJzIjpbeyJlbHQiOlsxNTZdLCJuYW1lIjoiZWx0ciJ9XX0sImN0ciI6NzJ9fSIgeyJuYW1lIjoibXMiLCJ2YWx1ZSI6eyJjdHIiOjc1fX0iL3sibmFtZSI6ImdjYyIsInZhbHVlIjp7InNlbGVjdGlvbiI6MCwiY3RyIjo4MX19Ild7Im5hbWUiOiJzd3QiLCJ2YWx1ZSI6eyJzbG4iOnsiZWlkIjoyNTAsInRycyI6W3siZWx0IjpbMTUyXSwibmFtZSI6ImVsdHIifV19LCJjdHIiOjg4fX0iL3sibmFtZSI6ImdjYyIsInZhbHVlIjp7InNlbGVjdGlvbiI6MywiY3RyIjo5N319Ilh7Im5hbWUiOiJzd3QiLCJ2YWx1ZSI6eyJzbG4iOnsiZWlkIjo1NDMsInRycyI6W3siZWx0IjpbMTkyXSwibmFtZSI6ImVsdHIifV19LCJjdHIiOjExMX19IjB7Im5hbWUiOiJnY2MiLCJ2YWx1ZSI6eyJzZWxlY3Rpb24iOjQsImN0ciI6MTE4fX0iMHsibmFtZSI6ImdjYyIsInZhbHVlIjp7InNlbGVjdGlvbiI6MCwiY3RyIjoxMjJ9fToWOgIIAToECAIQBToECAMQAToECAQQBA==
|
||||
Reference in New Issue
Block a user