Files
Singbox-For-SBPanel/protocol/sbproxy/java_server.go
2026-04-21 17:15:37 +08:00

122 lines
2.8 KiB
Go

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
if _, err := io.ReadFull(conn, b[:]); err != nil {
return
}
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, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
// Login Start
_, _, 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)
}