mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2025-01-24 22:01:49 +01:00
close #116, ignore closedchannelexception, update ktor
This commit is contained in:
parent
4faedc7894
commit
f799856df1
@ -64,7 +64,7 @@ dependencies {
|
||||
implementation("org.apache.commons:commons-compress:1.20")
|
||||
implementation("org.tukaani:xz:1.9")
|
||||
|
||||
val ktorVersion = "1.5.2"
|
||||
val ktorVersion = "1.5.3"
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation("io.ktor:ktor-network-tls-certificates:$ktorVersion")
|
||||
implementation("io.ktor:ktor-server-netty:$ktorVersion")
|
||||
|
@ -25,8 +25,6 @@ import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import javax.naming.NameNotFoundException
|
||||
import javax.naming.ServiceUnavailableException
|
||||
import javax.naming.directory.InitialDirContext
|
||||
|
||||
val badLength = DecoderException("Invalid length!")
|
||||
@ -41,7 +39,7 @@ fun resolveSrv(address: String, port: Int): Pair<String, Int> {
|
||||
try {
|
||||
// https://github.com/GeyserMC/Geyser/blob/99e72f35b308542cf0dbfb5b58816503c3d6a129/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
|
||||
val attr = InitialDirContext()
|
||||
.getAttributes("dns:///_minecraft._tcp.$address", arrayOf("SRV"))["SRV"]
|
||||
.getAttributes("dns:///_minecraft._tcp.$address", arrayOf("SRV"))["SRV"]
|
||||
if (attr != null && attr.size() > 0) {
|
||||
val record = (attr.get(0) as String).split(" ")
|
||||
return record[3] to record[2].toInt()
|
||||
@ -75,8 +73,8 @@ fun mcCfb8(key: ByteArray, mode: Int): Cipher {
|
||||
fun parseUndashedId(string: String): UUID {
|
||||
Preconditions.checkArgument(string.length == 32, "Length is incorrect")
|
||||
return UUID(
|
||||
string.substring(0, 16).toULong(16).toLong(),
|
||||
string.substring(16).toULong(16).toLong()
|
||||
string.substring(0, 16).toULong(16).toLong(),
|
||||
string.substring(16).toULong(16).toLong()
|
||||
)
|
||||
}
|
||||
|
||||
@ -95,7 +93,8 @@ fun twosComplementHexdigest(digest: ByteArray): String {
|
||||
|
||||
// https://github.com/VelocityPowered/Velocity/blob/e3f17eeb245b8d570f16c1f2aff5e7eafb698d5e/api/src/main/java/com/velocitypowered/api/util/UuidUtils.java
|
||||
fun generateOfflinePlayerUuid(username: String) = UUID.nameUUIDFromBytes(
|
||||
"OfflinePlayer:$username".toByteArray(Charsets.UTF_8))
|
||||
"OfflinePlayer:$username".toByteArray(Charsets.UTF_8)
|
||||
)
|
||||
|
||||
fun checkLocalAddress(inetAddress: InetAddress): Boolean {
|
||||
return VIAaaSConfig.blockLocalAddress && (inetAddress.isAnyLocalAddress
|
||||
@ -107,16 +106,15 @@ fun checkLocalAddress(inetAddress: InetAddress): Boolean {
|
||||
|| inetAddress.isMCOrgLocal
|
||||
|| inetAddress.isMCSiteLocal
|
||||
|| NetworkInterface.networkInterfaces().flatMap { it.inetAddresses() }
|
||||
.anyMatch {
|
||||
// This public address acts like a localhost, let's block it
|
||||
it == inetAddress
|
||||
})
|
||||
.anyMatch {
|
||||
// This public address acts like a localhost, let's block it
|
||||
it == inetAddress
|
||||
})
|
||||
}
|
||||
|
||||
fun matchesAddress(addr: InetSocketAddress, list: List<String>): Boolean {
|
||||
return (matchAddress(addr.hostString, list)
|
||||
|| (addr.address != null && (matchAddress(addr.address.hostAddress, list)
|
||||
|| matchAddress(addr.address.hostName, list))))
|
||||
return (matchAddress(addr.hostString, list) || (addr.address != null
|
||||
&& (matchAddress(addr.address.hostAddress, list) || matchAddress(addr.address.hostName, list))))
|
||||
}
|
||||
|
||||
private fun matchAddress(addr: String, list: List<String>): Boolean {
|
||||
@ -157,9 +155,9 @@ fun ByteBuf.readByteArray(length: Int) = ByteArray(length).also { 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"
|
||||
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" +
|
||||
UrlEscapers.urlFormParameterEscaper().escape(username) +
|
||||
"&serverId=$hash"
|
||||
) ?: throw IllegalArgumentException("Couldn't authenticate with session servers")
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import io.netty.channel.SimpleChannelInboundHandler
|
||||
import io.netty.handler.proxy.Socks5ProxyHandler
|
||||
import us.myles.ViaVersion.exception.CancelCodecException
|
||||
import java.net.SocketAddress
|
||||
import java.nio.channels.ClosedChannelException
|
||||
|
||||
class MinecraftHandler(
|
||||
val data: ConnectionData,
|
||||
@ -44,6 +45,7 @@ class MinecraftHandler(
|
||||
|
||||
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
|
||||
if (cause is CancelCodecException) return
|
||||
if (cause is ClosedChannelException) return
|
||||
mcLogger.debug("Exception: ", cause)
|
||||
disconnect("Exception: $cause")
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import io.netty.channel.ChannelFuture
|
||||
import io.netty.channel.ChannelInitializer
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler
|
||||
import io.netty.resolver.NoopAddressResolverGroup
|
||||
import io.netty.util.concurrent.Future
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion
|
||||
import us.myles.ViaVersion.packets.State
|
||||
@ -35,6 +36,7 @@ object ProtocolDetector {
|
||||
try {
|
||||
val ch: ChannelFuture = Bootstrap()
|
||||
.group(childLoop)
|
||||
.resolver(NoopAddressResolverGroup.INSTANCE)
|
||||
.channelFactory(channelSocketFactory(childLoop))
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.IP_TOS, 0x18)
|
||||
|
@ -11,6 +11,7 @@ import io.netty.channel.ChannelFuture
|
||||
import io.netty.channel.ChannelFutureListener
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.channel.socket.SocketChannel
|
||||
import io.netty.resolver.NoopAddressResolverGroup
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
@ -29,6 +30,7 @@ private fun createBackChannel(handler: MinecraftHandler, socketAddr: InetSocketA
|
||||
.option(ChannelOption.IP_TOS, 0x18)
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) // We need to show the error before the client timeout
|
||||
.resolver(NoopAddressResolverGroup.INSTANCE)
|
||||
.connect(socketAddr)
|
||||
.addListener(ChannelFutureListener {
|
||||
if (it.isSuccess) {
|
||||
@ -50,8 +52,7 @@ private fun createBackChannel(handler: MinecraftHandler, socketAddr: InetSocketA
|
||||
|
||||
private fun tryBackAddress(
|
||||
handler: MinecraftHandler,
|
||||
iterator: Iterator<InetAddress>,
|
||||
port: Int,
|
||||
iterator: Iterator<InetSocketAddress>,
|
||||
state: State,
|
||||
success: () -> Unit,
|
||||
) {
|
||||
@ -60,13 +61,13 @@ private fun tryBackAddress(
|
||||
// We're in the event loop
|
||||
handler.disconnect("Couldn't connect: $e")
|
||||
} else if (handler.data.frontChannel.isActive) {
|
||||
tryBackAddress(handler, iterator, port, state, success)
|
||||
tryBackAddress(handler, iterator, state, success)
|
||||
}
|
||||
}
|
||||
try {
|
||||
val socketAddr = InetSocketAddress(iterator.next(), port)
|
||||
val socketAddr = iterator.next()
|
||||
|
||||
if (checkLocalAddress(socketAddr.address)
|
||||
if ((socketAddr.address != null && checkLocalAddress(socketAddr.address))
|
||||
|| matchesAddress(socketAddr, VIAaaSConfig.blockedBackAddresses)
|
||||
|| !matchesAddress(socketAddr, VIAaaSConfig.allowedBackAddresses)
|
||||
) {
|
||||
@ -93,14 +94,21 @@ fun connectBack(handler: MinecraftHandler, address: String, port: Int, state: St
|
||||
try {
|
||||
val srvResolved = resolveSrv(address, port)
|
||||
|
||||
val iterator = InetAddress.getAllByName(srvResolved.first)
|
||||
.groupBy { it is Inet4Address }
|
||||
.toSortedMap() // I'm sorry, IPv4, but my true love is IPv6... We can still be friends though...
|
||||
.map { it.value.random() }
|
||||
.iterator()
|
||||
val removedEndDot = srvResolved.first.replace(Regex("\\.$"), "")
|
||||
|
||||
val iterator =
|
||||
if (!removedEndDot.endsWith(".onion")) {
|
||||
InetAddress.getAllByName(srvResolved.first)
|
||||
.groupBy { it is Inet4Address }
|
||||
.toSortedMap() // I'm sorry, IPv4, but my true love is IPv6... We can still be friends though...
|
||||
.map { InetSocketAddress(it.value.random(), srvResolved.second) }
|
||||
.iterator()
|
||||
} else {
|
||||
listOf(InetSocketAddress.createUnresolved(removedEndDot, srvResolved.second)).iterator()
|
||||
}
|
||||
|
||||
if (!iterator.hasNext()) throw IllegalArgumentException("Hostname has no IP address")
|
||||
tryBackAddress(handler, iterator, srvResolved.second, state, success)
|
||||
tryBackAddress(handler, iterator, state, success)
|
||||
} catch (e: Exception) {
|
||||
handler.data.frontChannel.eventLoop().submit {
|
||||
handler.disconnect("Couldn't connect: $e")
|
||||
|
Loading…
Reference in New Issue
Block a user