mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2024-10-01 05:08:08 +02:00
moved some code, authenticate online mode before connecting to backend
This commit is contained in:
parent
33b40e6eea
commit
e14f3eb121
@ -2,7 +2,10 @@ package com.github.creeper123123321.viaaas
|
||||
|
||||
import com.github.creeper123123321.viaaas.config.VIAaaSConfig
|
||||
import com.google.common.base.Preconditions
|
||||
import com.google.common.net.UrlEscapers
|
||||
import com.google.common.primitives.Ints
|
||||
import com.google.gson.JsonObject
|
||||
import io.ktor.client.request.*
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.handler.codec.DecoderException
|
||||
@ -135,4 +138,20 @@ fun writeFlushClose(ch: Channel, obj: Any) {
|
||||
|
||||
val secureRandom = if (VIAaaSConfig.useStrongRandom) SecureRandom.getInstanceStrong() else SecureRandom()
|
||||
|
||||
fun readableToByteArray(byteBuf: ByteBuf) = ByteArray(byteBuf.readableBytes()).also { byteBuf.readBytes(it) }
|
||||
fun readableToByteArray(byteBuf: ByteBuf) = ByteArray(byteBuf.readableBytes()).also { byteBuf.readBytes(it) }
|
||||
|
||||
suspend fun hasJoined(username: String, hash: String): JsonObject {
|
||||
return httpClient.get(
|
||||
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" +
|
||||
UrlEscapers.urlFormParameterEscaper().escape(username) +
|
||||
"&serverId=$hash"
|
||||
) ?: throw IllegalArgumentException("Couldn't authenticate with session servers")
|
||||
}
|
||||
|
||||
fun generate128Bits() = ByteArray(16).also { secureRandom.nextBytes(it) }
|
||||
|
||||
fun generateServerId() = "VIAaaS" + ByteArray(10).let {
|
||||
secureRandom.nextBytes(it)
|
||||
Base64.getEncoder().withoutPadding().encodeToString(it)
|
||||
// https://developer.mozilla.org/en-US/docs/Glossary/Base64 133% of original
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package com.github.creeper123123321.viaaas.command.sub
|
||||
|
||||
import com.github.creeper123123321.viaaas.command.VIAaaSConsole
|
||||
import com.github.creeper123123321.viaaas.handler.MinecraftHandler
|
||||
import us.myles.ViaVersion.api.Via
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender
|
||||
@ -23,8 +22,7 @@ object ConnectionsSubCommand : ViaSubCommand() {
|
||||
}
|
||||
val pAddr =
|
||||
it.channel?.pipeline()?.get(MinecraftHandler::class.java)?.other?.remoteAddress()
|
||||
val pName = it.channel?.pipeline()?.get(MinecraftHandler::class.java)?.data?.frontName
|
||||
p0.sendMessage("$pAddr $pVer ($pName) -> $backVer ($backName) $backAddr")
|
||||
p0.sendMessage("$pAddr $pVer -> $backVer ($backName) $backAddr")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ class BackEndInit(val connectionData: ConnectionData) : ChannelInitializer<Chann
|
||||
.addLast("via-codec", ViaCodec(user))
|
||||
.addLast("mc", MinecraftCodec())
|
||||
.also {
|
||||
if (connectionData.backVer == null) {
|
||||
if (connectionData.viaBackServerVer == null) {
|
||||
it.addLast("protocol-detector", ProtocolDetectorHandler(connectionData))
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,8 @@ class ConnectionData(
|
||||
val frontChannel: Channel,
|
||||
var backChannel: Channel? = null,
|
||||
var state: MinecraftConnectionState = HandshakeState(),
|
||||
var frontOnline: Boolean? = null, // todo
|
||||
var frontName: String? = null,
|
||||
var backName: String? = null,
|
||||
var frontVer: Int? = null,
|
||||
var backVer: Int? = null,
|
||||
var viaBackServerVer: Int? = null,
|
||||
) {
|
||||
val frontHandler get() = frontChannel.pipeline().get(MinecraftHandler::class.java)
|
||||
val backHandler get() = backChannel?.pipeline()?.get(MinecraftHandler::class.java)
|
||||
|
@ -32,9 +32,9 @@ class ProtocolDetectorHandler(val connectionData: ConnectionData) : ChannelDuple
|
||||
ProtocolDetector.detectVersion(ctx.channel().remoteAddress() as InetSocketAddress)
|
||||
.whenComplete { protocol, _ ->
|
||||
if (protocol != null && protocol.version != -1) {
|
||||
connectionData.backVer = protocol.version
|
||||
connectionData.viaBackServerVer = protocol.version
|
||||
} else {
|
||||
connectionData.backVer = 47 // fallback
|
||||
connectionData.viaBackServerVer = 47 // fallback
|
||||
}
|
||||
|
||||
ctx.pipeline().remove(this)
|
||||
|
@ -1,36 +1,15 @@
|
||||
package com.github.creeper123123321.viaaas.handler.state
|
||||
|
||||
import com.github.creeper123123321.viaaas.*
|
||||
import com.github.creeper123123321.viaaas.packet.handshake.Handshake
|
||||
import com.github.creeper123123321.viaaas.packet.Packet
|
||||
import com.github.creeper123123321.viaaas.VIAaaSAddress
|
||||
import com.github.creeper123123321.viaaas.config.VIAaaSConfig
|
||||
import com.github.creeper123123321.viaaas.handler.BackEndInit
|
||||
import com.github.creeper123123321.viaaas.handler.MinecraftHandler
|
||||
import com.github.creeper123123321.viaaas.handler.forward
|
||||
import io.netty.bootstrap.Bootstrap
|
||||
import io.netty.channel.ChannelFuture
|
||||
import com.github.creeper123123321.viaaas.mcLogger
|
||||
import com.github.creeper123123321.viaaas.packet.Packet
|
||||
import com.github.creeper123123321.viaaas.packet.handshake.Handshake
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.channel.socket.SocketChannel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import us.myles.ViaVersion.packets.State
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
|
||||
class HandshakeState : MinecraftConnectionState {
|
||||
fun connectBack(handler: MinecraftHandler, socketAddr: InetSocketAddress): ChannelFuture {
|
||||
return Bootstrap()
|
||||
.handler(BackEndInit(handler.data))
|
||||
.channelFactory(channelSocketFactory())
|
||||
.group(handler.data.frontChannel.eventLoop())
|
||||
.option(ChannelOption.IP_TOS, 0x18)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15_000) // Half of mc timeout
|
||||
.connect(socketAddr)
|
||||
}
|
||||
|
||||
override val state: State
|
||||
get() = State.HANDSHAKE
|
||||
|
||||
@ -55,55 +34,30 @@ class HandshakeState : MinecraftConnectionState {
|
||||
VIAaaSConfig.defaultBackendPort
|
||||
}
|
||||
|
||||
handler.data.backVer = backProto
|
||||
handler.data.frontOnline = parsed.online
|
||||
if (VIAaaSConfig.forceOnlineMode) handler.data.frontOnline = true
|
||||
handler.data.backName = parsed.username
|
||||
handler.data.viaBackServerVer = backProto
|
||||
var frontOnline = parsed.online
|
||||
if (VIAaaSConfig.forceOnlineMode) frontOnline = true
|
||||
|
||||
(handler.data.state as? LoginState)?.also {
|
||||
it.frontOnline = frontOnline
|
||||
it.backName = parsed.username
|
||||
it.backAddress = packet.address to packet.port
|
||||
}
|
||||
|
||||
val playerAddr = handler.data.frontHandler.remoteAddress
|
||||
mcLogger.info("Connecting ${handler.data.state.state} $playerAddr (${handler.data.frontVer}) -> ${packet.address}:${packet.port} ($backProto)")
|
||||
mcLogger.info(
|
||||
"Handshake: ${handler.data.state.state} $playerAddr (${handler.data.frontVer}," +
|
||||
" O: ${
|
||||
frontOnline.toString().substring(0, 1)
|
||||
}) -> ${packet.address}:${packet.port} (${backProto ?: "AUTO"})"
|
||||
)
|
||||
|
||||
if (!hadHostname && VIAaaSConfig.requireHostName) {
|
||||
throw UnsupportedOperationException("This VIAaaS instance requires you to use the hostname")
|
||||
}
|
||||
|
||||
handler.data.frontChannel.setAutoRead(false)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val srvResolved = resolveSrv(packet.address, packet.port)
|
||||
packet.address = srvResolved.first
|
||||
packet.port = srvResolved.second
|
||||
|
||||
val socketAddr = InetSocketAddress(InetAddress.getByName(packet.address), packet.port)
|
||||
|
||||
if (checkLocalAddress(socketAddr.address)
|
||||
|| matchesAddress(socketAddr, VIAaaSConfig.blockedBackAddresses)
|
||||
|| !matchesAddress(socketAddr, VIAaaSConfig.allowedBackAddresses)
|
||||
) {
|
||||
throw SecurityException("Not allowed")
|
||||
}
|
||||
|
||||
val future = connectBack(handler, socketAddr)
|
||||
|
||||
future.addListener {
|
||||
if (it.isSuccess) {
|
||||
mcLogger.info("Connected ${handler.remoteAddress} -> $socketAddr")
|
||||
|
||||
handler.data.backChannel = future.channel() as SocketChannel
|
||||
|
||||
forward(handler, packet, true)
|
||||
|
||||
handler.data.frontChannel.setAutoRead(true)
|
||||
} else {
|
||||
// We're in the event loop
|
||||
handler.disconnect("Couldn't connect: " + it.cause().toString())
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
handler.data.frontChannel.eventLoop().submit {
|
||||
handler.disconnect("Couldn't connect: $e")
|
||||
}
|
||||
}
|
||||
if (packet.nextState == State.STATUS) {
|
||||
connectBack(handler, packet.address, packet.port, packet.nextState) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,11 @@ package com.github.creeper123123321.viaaas.handler.state
|
||||
import com.github.creeper123123321.viaaas.*
|
||||
import com.github.creeper123123321.viaaas.codec.CompressionCodec
|
||||
import com.github.creeper123123321.viaaas.codec.CryptoCodec
|
||||
import com.github.creeper123123321.viaaas.packet.*
|
||||
import com.github.creeper123123321.viaaas.packet.login.*
|
||||
import com.github.creeper123123321.viaaas.handler.MinecraftHandler
|
||||
import com.github.creeper123123321.viaaas.handler.forward
|
||||
import com.google.common.net.UrlEscapers
|
||||
import com.github.creeper123123321.viaaas.packet.*
|
||||
import com.github.creeper123123321.viaaas.packet.login.*
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import io.ktor.client.request.*
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -19,11 +17,17 @@ import us.myles.ViaVersion.packets.State
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import javax.crypto.Cipher
|
||||
import io.netty.channel.Channel
|
||||
|
||||
class LoginState : MinecraftConnectionState {
|
||||
val callbackPlayerId = CompletableFuture<String>()
|
||||
lateinit var frontToken: ByteArray
|
||||
lateinit var frontServerId: String
|
||||
var frontOnline: Boolean? = null
|
||||
lateinit var frontName: String
|
||||
lateinit var backAddress: Pair<String, Int>
|
||||
var backName: String? = null
|
||||
var started = false
|
||||
override val state: State
|
||||
get() = State.LOGIN
|
||||
|
||||
@ -67,71 +71,58 @@ class LoginState : MinecraftConnectionState {
|
||||
}
|
||||
}
|
||||
|
||||
fun authenticateOnlineFront(frontHandler: MinecraftHandler) {
|
||||
val id = "VIAaaS" + ByteArray(10).let {
|
||||
secureRandom.nextBytes(it)
|
||||
Base64.getEncoder().withoutPadding().encodeToString(it)
|
||||
// https://developer.mozilla.org/en-US/docs/Glossary/Base64 133% of original
|
||||
}
|
||||
fun authenticateOnlineFront(frontChannel: Channel) {
|
||||
// We'll use non-vanilla server id, public key size and token size
|
||||
val token = ByteArray(16).let {
|
||||
secureRandom.nextBytes(it)
|
||||
it
|
||||
}
|
||||
frontToken = token
|
||||
frontServerId = id
|
||||
frontToken = generate128Bits()
|
||||
frontServerId = generateServerId()
|
||||
|
||||
val cryptoRequest = CryptoRequest()
|
||||
cryptoRequest.serverId = id
|
||||
cryptoRequest.serverId = frontServerId
|
||||
cryptoRequest.publicKey = mcCryptoKey.public
|
||||
cryptoRequest.token = token
|
||||
cryptoRequest.token = frontToken
|
||||
|
||||
send(frontHandler.data.frontChannel, cryptoRequest, true)
|
||||
send(frontChannel, cryptoRequest, true)
|
||||
}
|
||||
|
||||
fun handleCryptoRequest(handler: MinecraftHandler, cryptoRequest: CryptoRequest) {
|
||||
val data = handler.data
|
||||
val backServerId = cryptoRequest.serverId
|
||||
val backPublicKey = cryptoRequest.publicKey
|
||||
val backToken = cryptoRequest.token
|
||||
|
||||
if (data.frontOnline == null) {
|
||||
authenticateOnlineFront(handler)
|
||||
if (frontOnline == null) {
|
||||
authenticateOnlineFront(handler.data.frontChannel)
|
||||
}
|
||||
|
||||
val backKey = ByteArray(16).let {
|
||||
secureRandom.nextBytes(it)
|
||||
it
|
||||
}
|
||||
val backHash = generateServerHash(backServerId, backKey, backPublicKey)
|
||||
|
||||
callbackPlayerId.whenComplete { playerId, e ->
|
||||
if (e != null) return@whenComplete
|
||||
val frontHandler = handler.data.frontHandler
|
||||
val backChan = handler.data.backChannel!!
|
||||
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val sessionJoin = viaWebServer.requestSessionJoin(
|
||||
parseUndashedId(playerId),
|
||||
handler.data.backName!!,
|
||||
backHash,
|
||||
frontHandler.remoteAddress!!, // Frontend handler
|
||||
backPublicKey
|
||||
)
|
||||
val backKey = generate128Bits()
|
||||
val backHash = generateServerHash(backServerId, backKey, backPublicKey)
|
||||
|
||||
val backChan = handler.data.backChannel!!
|
||||
sessionJoin.whenCompleteAsync({ _, throwable ->
|
||||
viaWebServer.requestSessionJoin(
|
||||
parseUndashedId(playerId),
|
||||
backName!!,
|
||||
backHash,
|
||||
frontHandler.remoteAddress!!,
|
||||
backPublicKey
|
||||
).whenCompleteAsync({ _, throwable ->
|
||||
if (throwable != null) {
|
||||
frontHandler.data.backHandler!!.disconnect("Online mode error: $throwable")
|
||||
} else {
|
||||
val cryptoResponse = CryptoResponse()
|
||||
cryptoResponse.encryptedKey = encryptRsa(backPublicKey, backKey)
|
||||
cryptoResponse.encryptedToken = encryptRsa(backPublicKey, backToken)
|
||||
forward(frontHandler, cryptoResponse, true)
|
||||
|
||||
val backAesEn = mcCfb8(backKey, Cipher.ENCRYPT_MODE)
|
||||
val backAesDe = mcCfb8(backKey, Cipher.DECRYPT_MODE)
|
||||
backChan.pipeline().addBefore("frame", "crypto", CryptoCodec(backAesDe, backAesEn))
|
||||
return@whenCompleteAsync
|
||||
}
|
||||
|
||||
val cryptoResponse = CryptoResponse()
|
||||
cryptoResponse.encryptedKey = encryptRsa(backPublicKey, backKey)
|
||||
cryptoResponse.encryptedToken = encryptRsa(backPublicKey, backToken)
|
||||
forward(frontHandler, cryptoResponse, true)
|
||||
|
||||
val backAesEn = mcCfb8(backKey, Cipher.ENCRYPT_MODE)
|
||||
val backAesDe = mcCfb8(backKey, Cipher.DECRYPT_MODE)
|
||||
backChan.pipeline().addBefore("frame", "crypto", CryptoCodec(backAesDe, backAesEn))
|
||||
}, backChan.eventLoop())
|
||||
} catch (e: Exception) {
|
||||
frontHandler.disconnect("Online mode error: $e")
|
||||
@ -143,14 +134,12 @@ class LoginState : MinecraftConnectionState {
|
||||
fun handleCryptoResponse(handler: MinecraftHandler, cryptoResponse: CryptoResponse) {
|
||||
val frontHash = let {
|
||||
val frontKey = decryptRsa(mcCryptoKey.private, cryptoResponse.encryptedKey)
|
||||
// RSA token - wat??? why is it encrypted with RSA if it was sent unencrypted?
|
||||
val decryptedToken = decryptRsa(mcCryptoKey.private, cryptoResponse.encryptedToken)
|
||||
|
||||
if (!decryptedToken.contentEquals(frontToken)) throw IllegalStateException("invalid token!")
|
||||
if (!decryptedToken.contentEquals(frontToken)) throw IllegalStateException("Invalid token!")
|
||||
|
||||
val aesEn = mcCfb8(frontKey, Cipher.ENCRYPT_MODE)
|
||||
val aesDe = mcCfb8(frontKey, Cipher.DECRYPT_MODE)
|
||||
|
||||
handler.data.frontChannel.pipeline().addBefore("frame", "crypto", CryptoCodec(aesDe, aesEn))
|
||||
|
||||
generateServerHash(frontServerId, frontKey, mcCryptoKey.public)
|
||||
@ -159,14 +148,9 @@ class LoginState : MinecraftConnectionState {
|
||||
handler.data.frontChannel.setAutoRead(false)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val profile = httpClient.get<JsonObject?>(
|
||||
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" +
|
||||
UrlEscapers.urlFormParameterEscaper().escape(handler.data.frontName!!) +
|
||||
"&serverId=$frontHash"
|
||||
) ?: throw IllegalArgumentException("Couldn't authenticate with session servers")
|
||||
|
||||
val profile = hasJoined(frontName, frontHash)
|
||||
val id = profile.get("id")!!.asString
|
||||
mcLogger.info("Validated front-end session: ${handler.data.frontName} $id")
|
||||
|
||||
callbackPlayerId.complete(id)
|
||||
} catch (e: Exception) {
|
||||
callbackPlayerId.completeExceptionally(e)
|
||||
@ -177,26 +161,34 @@ class LoginState : MinecraftConnectionState {
|
||||
|
||||
fun handleLoginStart(handler: MinecraftHandler, loginStart: LoginStart) {
|
||||
if (loginStart.username.length > 16) throw badLength
|
||||
if (handler.data.frontName != null) throw IllegalStateException("Login already started")
|
||||
if (started) throw IllegalStateException("Login already started")
|
||||
started = true
|
||||
|
||||
handler.data.frontName = loginStart.username
|
||||
handler.data.backName = handler.data.backName ?: handler.data.frontName
|
||||
frontName = loginStart.username
|
||||
backName = backName ?: frontName
|
||||
|
||||
loginStart.username = handler.data.backName!!
|
||||
|
||||
callbackPlayerId.whenComplete { _, e -> if (e != null) disconnect(handler, "Profile error: $e") }
|
||||
|
||||
if (handler.data.frontOnline == false) {
|
||||
callbackPlayerId.complete(generateOfflinePlayerUuid(handler.data.frontName!!).toString().replace("-", ""))
|
||||
val connect = {
|
||||
connectBack(handler, backAddress.first, backAddress.second, State.LOGIN) {
|
||||
loginStart.username = backName!!
|
||||
send(handler.data.backChannel!!, loginStart, true)
|
||||
}
|
||||
}
|
||||
|
||||
if (handler.data.frontOnline == true) { // forced
|
||||
authenticateOnlineFront(handler.data.backHandler!!)
|
||||
callbackPlayerId.whenComplete { _, e ->
|
||||
if (e == null) forward(handler, loginStart, true)
|
||||
callbackPlayerId.whenComplete { id, e ->
|
||||
if (e != null) {
|
||||
disconnect(handler, "Profile error: $e")
|
||||
} else {
|
||||
mcLogger.info("Login: ${handler.remoteAddress} $frontName $id")
|
||||
if (frontOnline != null) {
|
||||
connect()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
forward(handler, loginStart)
|
||||
}
|
||||
|
||||
when (frontOnline) {
|
||||
false -> callbackPlayerId.complete(generateOfflinePlayerUuid(frontName).toString().replace("-", ""))
|
||||
true -> authenticateOnlineFront(handler.data.frontChannel) // forced
|
||||
null -> connect() // Connect then authenticate
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ object PlayState : MinecraftConnectionState {
|
||||
Type.STRING.read(Unpooled.wrappedBuffer(pluginMessage.data))
|
||||
} + " (VIAaaS C: ${ProtocolVersion.getProtocol(handler.data.frontVer!!)} S: ${
|
||||
ProtocolVersion.getProtocol(
|
||||
handler.data.backVer!!
|
||||
handler.data.viaBackServerVer!!
|
||||
)
|
||||
})"
|
||||
|
||||
|
@ -38,7 +38,7 @@ object StatusState : MinecraftConnectionState {
|
||||
it.addProperty(
|
||||
"name",
|
||||
"§9VIAaaS§r (C: §7${ProtocolVersion.getProtocol(handler.data.frontVer!!)}§r S: §7${
|
||||
ProtocolVersion.getProtocol(handler.data.backVer!!)
|
||||
ProtocolVersion.getProtocol(handler.data.viaBackServerVer!!)
|
||||
}§r)"
|
||||
)
|
||||
})
|
||||
|
@ -0,0 +1,73 @@
|
||||
package com.github.creeper123123321.viaaas.handler.state
|
||||
|
||||
import com.github.creeper123123321.viaaas.*
|
||||
import com.github.creeper123123321.viaaas.config.VIAaaSConfig
|
||||
import com.github.creeper123123321.viaaas.handler.BackEndInit
|
||||
import com.github.creeper123123321.viaaas.handler.MinecraftHandler
|
||||
import com.github.creeper123123321.viaaas.handler.forward
|
||||
import com.github.creeper123123321.viaaas.packet.handshake.Handshake
|
||||
import io.netty.bootstrap.Bootstrap
|
||||
import io.netty.channel.ChannelFuture
|
||||
import io.netty.channel.ChannelFutureListener
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.channel.socket.SocketChannel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import us.myles.ViaVersion.packets.State
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
|
||||
fun createBackChannel(handler: MinecraftHandler, socketAddr: InetSocketAddress, state: State): ChannelFuture {
|
||||
return Bootstrap()
|
||||
.handler(BackEndInit(handler.data))
|
||||
.channelFactory(channelSocketFactory())
|
||||
.group(handler.data.frontChannel.eventLoop())
|
||||
.option(ChannelOption.IP_TOS, 0x18)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15_000) // Half of mc timeout
|
||||
.connect(socketAddr)
|
||||
.addListener(ChannelFutureListener {
|
||||
if (it.isSuccess) {
|
||||
mcLogger.info("Connected ${handler.remoteAddress} -> $socketAddr")
|
||||
handler.data.backChannel = it.channel() as SocketChannel
|
||||
|
||||
val packet = Handshake()
|
||||
packet.nextState = state
|
||||
packet.protocolId = handler.data.frontVer!!
|
||||
packet.address = socketAddr.hostString
|
||||
packet.port = socketAddr.port
|
||||
|
||||
forward(handler, packet, true)
|
||||
|
||||
handler.data.frontChannel.setAutoRead(true)
|
||||
} else {
|
||||
// We're in the event loop
|
||||
handler.disconnect("Couldn't connect: " + it.cause().toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun connectBack(handler: MinecraftHandler, address: String, port: Int, state: State, success: () -> Unit) {
|
||||
handler.data.frontChannel.setAutoRead(false)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val srvResolved = resolveSrv(address, port)
|
||||
|
||||
val socketAddr = InetSocketAddress(InetAddress.getByName(srvResolved.first), srvResolved.second)
|
||||
|
||||
if (checkLocalAddress(socketAddr.address)
|
||||
|| matchesAddress(socketAddr, VIAaaSConfig.blockedBackAddresses)
|
||||
|| !matchesAddress(socketAddr, VIAaaSConfig.allowedBackAddresses)
|
||||
) {
|
||||
throw SecurityException("Not allowed")
|
||||
}
|
||||
|
||||
createBackChannel(handler, socketAddr, state).addListener { if (it.isSuccess) success() }
|
||||
} catch (e: Exception) {
|
||||
handler.data.frontChannel.eventLoop().submit {
|
||||
handler.disconnect("Couldn't connect: $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import us.myles.ViaVersion.protocols.base.VersionProvider
|
||||
|
||||
object AspirinVersionProvider : VersionProvider() {
|
||||
override fun getServerProtocol(connection: UserConnection): Int {
|
||||
val ver = connection.channel!!.pipeline().get(MinecraftHandler::class.java).data.backVer
|
||||
val ver = connection.channel!!.pipeline().get(MinecraftHandler::class.java).data.viaBackServerVer
|
||||
if (ver != null) return ver
|
||||
return super.getServerProtocol(connection)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user