新增协议SBProxy-MC
This commit is contained in:
120
protocol/sbproxy/java_server.go
Normal file
120
protocol/sbproxy/java_server.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package sbproxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
func (h *Inbound) handleJavaConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
_, _, err := ReadVarInt(conn) // packet len
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
packetID, _, err := ReadVarInt(conn)
|
||||
if err != nil || packetID != 0x00 {
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
ReadVarInt(conn) // protocol version
|
||||
ReadString(conn) // server address
|
||||
binary.Read(conn, binary.BigEndian, new(uint16))
|
||||
nextState, _, _ := ReadVarInt(conn)
|
||||
|
||||
switch nextState {
|
||||
case 1: // Status
|
||||
h.handleJavaStatus(conn)
|
||||
case 2: // Login
|
||||
h.handleJavaLogin(ctx, conn, metadata, onClose)
|
||||
default:
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Inbound) handleJavaStatus(conn net.Conn) {
|
||||
for {
|
||||
packetLen, _, err := ReadVarInt(conn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
packetID, _, err := ReadVarInt(conn)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if packetID == 0x00 { // Status Request
|
||||
motd := h.options.MOTD
|
||||
if motd == "" {
|
||||
motd = "A Minecraft Server"
|
||||
}
|
||||
ver := h.options.Version
|
||||
if ver == "" {
|
||||
ver = "1.20.1"
|
||||
}
|
||||
|
||||
resp := map[string]any{
|
||||
"version": map[string]any{"name": ver, "protocol": 763},
|
||||
"players": map[string]any{"max": h.options.MaxPlayers, "online": 0, "sample": []any{}},
|
||||
"description": map[string]any{"text": motd},
|
||||
}
|
||||
data, _ := json.Marshal(resp)
|
||||
|
||||
var body bytes.Buffer
|
||||
WriteVarInt(&body, 0x00) // Response ID
|
||||
WriteString(&body, string(data))
|
||||
|
||||
WriteVarInt(conn, int32(body.Len()))
|
||||
conn.Write(body.Bytes())
|
||||
} else if packetID == 0x01 { // Ping
|
||||
var b [8]byte
|
||||
io.ReadFull(conn, b[:])
|
||||
|
||||
var body bytes.Buffer
|
||||
WriteVarInt(&body, 0x01)
|
||||
body.Write(b[:])
|
||||
|
||||
WriteVarInt(conn, int32(body.Len()))
|
||||
conn.Write(body.Bytes())
|
||||
return
|
||||
} else {
|
||||
io.CopyN(io.Discard, conn, int64(packetLen)-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Inbound) handleJavaLogin(ctx context.Context, conn net.Conn, username string, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
// Note: Packet length is already read in switch or caller
|
||||
// Login Start
|
||||
packetLen, _, err := ReadVarInt(conn)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
packetID, _, err := ReadVarInt(conn)
|
||||
if err != nil || packetID != 0x00 {
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
user, _ := ReadString(conn)
|
||||
|
||||
// Offline Mode: No encryption/auth sequence, just Login Success
|
||||
var loginSuccess bytes.Buffer
|
||||
WriteVarInt(&loginSuccess, 0x02) // Login Success ID
|
||||
// UUID (offline)
|
||||
loginSuccess.Write(make([]byte, 16))
|
||||
WriteString(&loginSuccess, user)
|
||||
WriteVarInt(&loginSuccess, 0) // No properties
|
||||
|
||||
WriteVarInt(conn, int32(loginSuccess.Len()))
|
||||
conn.Write(loginSuccess.Bytes())
|
||||
|
||||
h.handlePlay(ctx, conn, user, metadata, onClose)
|
||||
}
|
||||
Reference in New Issue
Block a user