mirror of
https://github.com/PretendoNetwork/nex-go.git
synced 2025-04-02 11:02:14 -04:00
Barebones PRUDP/NEX server library written in Go
.gitignore | ||
client.go | ||
common.go | ||
compression.go | ||
kerberos.go | ||
nex_stream.go | ||
packet.go | ||
packet_v0.go | ||
packet_v1.go | ||
README.md | ||
rmc.go | ||
server.go | ||
types.go |
NEX related libraries to make NEX servers in Go
How to install and use
Install
go get https://github.com/PretendoNetwork/nex-go
Usage
package main
import (
"fmt"
NEX "https://github.com/PretendoNetwork/nex-go"
)
// Bare-bones example of the structure of the Friends service AUTH server for the WiiU/3DS
/*
THIS IS VERY ROUGH EXAMPLE, USING TECHNIQUES THAT SHOULD NOT BE USED
NO REAL AUTHENTICATION OR CHECKS ARE GOING ON, THIS EXAMPLE JUST
BRUTE-FORCES THE USER THROUGH AUTHENTICATION.
*/
func main() {
settings := NEX.NewSettings()
settings.PrudpVersion = 0
settings.PrudpV0SignatureVersion = 1
settings.KerberosKeySize = 16
settings.AccessKey = "ridfebb9"
fmt.Println("STARTING FRIENDS AUTH SERVER")
Server := NEX.NewServer(settings)
Server.On("Packet", func(Client *NEX.Client, Packet *NEX.Packet) {
// Acknowledge every packet if it needs it. If it makes it this far, it's good
if Packet.HasFlag(NEX.Flags["NeedAck"]) {
Server.Acknowledge(Packet)
}
})
Server.On("Data", func(Client *NEX.Client, Packet *NEX.Packet) {
stream := NEX.NewInputStream(Packet.RMCRequest.Parameters)
response := NEX.NewRMCResponse(0x0A, Packet.RMCRequest.Header.CallID)
responseStream := NEX.NewOutputStream()
ResponsePacket := NEX.NewPacket(Client)
ResponsePacket.SetVersion(0)
ResponsePacket.SetSource(Packet.Destination)
ResponsePacket.SetDestination(Packet.Source)
ResponsePacket.SetType(NEX.Types["Data"])
pid := 1234567890 // account PID/NEX username (dummy)
password := "nex_password" // account NEX password (dummy)
key := []byte(password)
for i := 0; i < 65000+pid%1024; i++ {
key = NEX.MD5Hash(key)
}
Kerberos := NEX.NewKerberos(string(key))
// Checking the Method ID in this way is generally bad.
// A better way would be to track each protocol and have a reference to it's methods stored by their ID,
// and dynamically getting the handler
if Packet.RMCRequest.Header.MethodID == 2 { // 0x0A::0x02 (LoginEx)
_ = stream.String() // username
_ = stream.DataHolder() // login data
Kerberos := NEX.NewKerberos(string(key))
str := "test string test" // dummy data
kerberosData := Kerberos.Encrypt([]byte(str))
JSONBuffer := []byte(`{
"stream": "10",
"type": "2",
"PID": "2",
"port": "60001",
"address": "127.0.0.1",
"sid": "1",
"CID": "1"
}`)
var JSON map[string]string
_ = json.Unmarshal(JSONBuffer, &JSON)
station := NEX.NewStationURL("prudps", JSON)
name := "branch:origin/feature/45925_FixAutoReconnect build:3_10_11_2006_0" // official server
responseStream.UInt32LE(uint32(0x00010001)) // success
responseStream.UInt32LE(uint32(pid))
responseStream.Buffer(kerberosData)
responseStream.String(station) // Station URL (normal)
responseStream.UInt32LE(uint32(0)) // Special protocols (unused)
responseStream.String("") // Station URL (special) (unused)
responseStream.String(name)
response.SetSuccess(uint32(2), responseStream.Bytes())
ResponsePacket.SetPayload(response.Bytes())
} else if Packet.RMCRequest.Header.MethodID == 3 { // 0x0A::0x03 (RequestTicket)
str := "test string test test string tes" // dummy data
_ = stream.UInt32LE() // User PID
_ = stream.UInt32LE() // Server PID?
responseStream.UInt32LE(uint32(0x00010001)) // success
kerberosStream := NEX.NewOutputStream()
kerberosStream.Write([]byte("I like chickens.")) // Kerberos key (dummy)
kerberosStream.UInt32LE(uint32(0xFFFFFFFF)) // Unknown PID
kerberosStream.Buffer([]byte(str)) // Kerberos data
kerberosData := Kerberos.Encrypt(kerberosStream.Bytes())
responseStream.Buffer(kerberosData)
response.SetSuccess(uint32(3), responseStream.Bytes())
} else {
panic("INVALID PROTOCOL METHOD ID " + string(Packet.RMCRequest.Header.MethodID))
}
ResponsePacket.SetPayload(response.Bytes())
Server.Send(Client, &ResponsePacket)
})
Server.Listen(":60000")
}