mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-02 21:20:55 +00:00
Tailscale Plugin :D
This commit is contained in:
parent
01a520777e
commit
1035c83166
@ -9,6 +9,7 @@ server.
|
|||||||
* foundation-bifrost: Discord chat bridge
|
* foundation-bifrost: Discord chat bridge
|
||||||
* foundation-chaos: Simulate chaos inside a minecraft world
|
* foundation-chaos: Simulate chaos inside a minecraft world
|
||||||
* foundation-heimdall: Event tracking
|
* foundation-heimdall: Event tracking
|
||||||
|
* foundation-tailscale: Connect the Minecraft Server to Tailscale
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
|
|
||||||
|
20
foundation-tailscale/build.gradle.kts
Normal file
20
foundation-tailscale/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
plugins {
|
||||||
|
id("gay.pizza.foundation.concrete-plugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "GitLabLibtailscale"
|
||||||
|
url = uri("https://gitlab.com/api/v4/projects/44435887/packages/maven")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":common-plugin"))
|
||||||
|
compileOnly(project(":foundation-shared"))
|
||||||
|
implementation(libs.tailscale)
|
||||||
|
}
|
||||||
|
|
||||||
|
concreteItem {
|
||||||
|
dependency(project(":foundation-core"))
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package gay.pizza.foundation.tailscale
|
||||||
|
|
||||||
|
import com.charleskorn.kaml.Yaml
|
||||||
|
import gay.pizza.foundation.common.BaseFoundationPlugin
|
||||||
|
import gay.pizza.foundation.common.FoundationCoreLoader
|
||||||
|
import gay.pizza.foundation.shared.PluginMainClass
|
||||||
|
import gay.pizza.foundation.shared.copyDefaultConfig
|
||||||
|
import kotlin.io.path.inputStream
|
||||||
|
|
||||||
|
@PluginMainClass
|
||||||
|
class FoundationTailscalePlugin : BaseFoundationPlugin() {
|
||||||
|
lateinit var config: TailscaleConfig
|
||||||
|
lateinit var controller: TailscaleController
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
val foundation = FoundationCoreLoader.get(server)
|
||||||
|
val configPath = copyDefaultConfig<FoundationTailscalePlugin>(
|
||||||
|
slF4JLogger,
|
||||||
|
foundation.pluginDataPath,
|
||||||
|
"tailscale.yaml"
|
||||||
|
)
|
||||||
|
config = Yaml.default.decodeFromStream(TailscaleConfig.serializer(), configPath.inputStream())
|
||||||
|
controller = TailscaleController(server, config)
|
||||||
|
controller.enable()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
controller.disable()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package gay.pizza.foundation.tailscale
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TailscaleConfig(
|
||||||
|
val enabled: Boolean = false,
|
||||||
|
val hostname: String,
|
||||||
|
val controlUrl: String? = null,
|
||||||
|
val authKey: String? = null,
|
||||||
|
val tailscalePath: String? = null,
|
||||||
|
val ephemeral: Boolean = false
|
||||||
|
)
|
@ -0,0 +1,38 @@
|
|||||||
|
package gay.pizza.foundation.tailscale
|
||||||
|
|
||||||
|
import gay.pizza.tailscale.core.Tailscale
|
||||||
|
import org.bukkit.Server
|
||||||
|
|
||||||
|
class TailscaleController(val server: Server, val config: TailscaleConfig) {
|
||||||
|
private val tailscale = Tailscale()
|
||||||
|
|
||||||
|
var tailscaleProxyServer: TailscaleProxyServer? = null
|
||||||
|
|
||||||
|
fun enable() {
|
||||||
|
if (!config.enabled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tailscale.hostname = config.hostname
|
||||||
|
|
||||||
|
if (config.controlUrl != null) {
|
||||||
|
tailscale.controlUrl = config.controlUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.authKey != null) {
|
||||||
|
tailscale.authKey = config.authKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.tailscalePath != null) {
|
||||||
|
tailscale.directoryPath = config.tailscalePath
|
||||||
|
}
|
||||||
|
|
||||||
|
tailscale.up()
|
||||||
|
tailscaleProxyServer = TailscaleProxyServer(server, tailscale)
|
||||||
|
tailscaleProxyServer?.listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disable() {
|
||||||
|
tailscaleProxyServer?.close()
|
||||||
|
tailscale.close()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package gay.pizza.foundation.tailscale
|
||||||
|
|
||||||
|
import gay.pizza.tailscale.core.Tailscale
|
||||||
|
import gay.pizza.tailscale.core.TailscaleConn
|
||||||
|
import gay.pizza.tailscale.core.TailscaleListener
|
||||||
|
import org.bukkit.Server
|
||||||
|
import java.net.InetSocketAddress
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.channels.ClosedChannelException
|
||||||
|
import java.nio.channels.ReadableByteChannel
|
||||||
|
import java.nio.channels.SocketChannel
|
||||||
|
import java.nio.channels.WritableByteChannel
|
||||||
|
|
||||||
|
class TailscaleProxyServer(val server: Server, val tailscale: Tailscale) {
|
||||||
|
private var minecraftServerListener: TailscaleListener? = null
|
||||||
|
|
||||||
|
fun listen() {
|
||||||
|
minecraftServerListener?.close()
|
||||||
|
minecraftServerListener = tailscale.listen("tcp", ":25565")
|
||||||
|
val thread = Thread {
|
||||||
|
minecraftServerListener?.threadedAcceptLoop { conn ->
|
||||||
|
handleServerConnection(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread.name = "Tailscale Accept Loop"
|
||||||
|
thread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleServerConnection(conn: TailscaleConn) {
|
||||||
|
val socketChannel = SocketChannel.open(InetSocketAddress("127.0.0.1", server.port))
|
||||||
|
val connChannel = conn.openReadWriteChannel()
|
||||||
|
|
||||||
|
fun closeAll() {
|
||||||
|
socketChannel.close()
|
||||||
|
connChannel.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startCopyThread(name: String, from: ReadableByteChannel, to: WritableByteChannel) {
|
||||||
|
val thread = Thread {
|
||||||
|
try {
|
||||||
|
while (from.isOpen && to.isOpen) {
|
||||||
|
val buffer = ByteBuffer.allocate(2048)
|
||||||
|
val size = from.read(buffer)
|
||||||
|
if (size < 0) {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
buffer.flip()
|
||||||
|
val array = buffer.array()
|
||||||
|
to.write(buffer)
|
||||||
|
}
|
||||||
|
buffer.clear()
|
||||||
|
}
|
||||||
|
} catch (_: ClosedChannelException) {
|
||||||
|
} finally {
|
||||||
|
closeAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thread.name = name
|
||||||
|
thread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
startCopyThread("Tailscale to Socket Pipe", connChannel, socketChannel)
|
||||||
|
startCopyThread("Socket to Tailscale Pipe", socketChannel, connChannel)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun close() {
|
||||||
|
minecraftServerListener?.close()
|
||||||
|
}
|
||||||
|
}
|
11
foundation-tailscale/src/main/resources/plugin.yml
Normal file
11
foundation-tailscale/src/main/resources/plugin.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
name: Foundation-Tailscale
|
||||||
|
version: '${version}'
|
||||||
|
main: gay.pizza.foundation.tailscale.FoundationTailscalePlugin
|
||||||
|
api-version: 1.18
|
||||||
|
prefix: Foundation-Tailscale
|
||||||
|
load: STARTUP
|
||||||
|
depend:
|
||||||
|
- Foundation
|
||||||
|
authors:
|
||||||
|
- kubeliv
|
||||||
|
- azenla
|
12
foundation-tailscale/src/main/resources/tailscale.yaml
Normal file
12
foundation-tailscale/src/main/resources/tailscale.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Whether Tailscale is enabled.
|
||||||
|
enabled: false
|
||||||
|
# Hostname for Tailscale node.
|
||||||
|
hostname: minecraft
|
||||||
|
# Tailscale control URL. Null for the default.
|
||||||
|
controlUrl: null
|
||||||
|
# Tailscale authentication key. Null for the default.
|
||||||
|
authKey: null
|
||||||
|
# Tailscale path. Null for the default.
|
||||||
|
tailscalePath: null
|
||||||
|
# Tailscale ephemeral mode.
|
||||||
|
ephemeral: false
|
@ -41,4 +41,3 @@ do
|
|||||||
# Download the plugin and store it at the mentioned path.
|
# Download the plugin and store it at the mentioned path.
|
||||||
curl --fail -Ls "$base_url/$artifact_path" --output "$dl_path" || (echo "Failed to download ${artifact_path}"; exit 1)
|
curl --fail -Ls "$base_url/$artifact_path" --output "$dl_path" || (echo "Failed to download ${artifact_path}"; exit 1)
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ include(
|
|||||||
":foundation-bifrost",
|
":foundation-bifrost",
|
||||||
":foundation-chaos",
|
":foundation-chaos",
|
||||||
":foundation-heimdall",
|
":foundation-heimdall",
|
||||||
|
":foundation-tailscale",
|
||||||
":tool-gjallarhorn",
|
":tool-gjallarhorn",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ dependencyResolutionManagement {
|
|||||||
version("postgresql", "42.5.3")
|
version("postgresql", "42.5.3")
|
||||||
version("exposed", "0.41.1")
|
version("exposed", "0.41.1")
|
||||||
version("hikaricp", "5.0.1")
|
version("hikaricp", "5.0.1")
|
||||||
|
version("libtailscale", "0.1.2-SNAPSHOT")
|
||||||
|
|
||||||
library("clikt", "com.github.ajalt.clikt", "clikt").versionRef("clikt")
|
library("clikt", "com.github.ajalt.clikt", "clikt").versionRef("clikt")
|
||||||
library("xodus-core", "org.jetbrains.xodus", "xodus-openAPI").versionRef("xodus")
|
library("xodus-core", "org.jetbrains.xodus", "xodus-openAPI").versionRef("xodus")
|
||||||
@ -90,6 +92,7 @@ dependencyResolutionManagement {
|
|||||||
library("exposed-jdbc", "org.jetbrains.exposed", "exposed-jdbc").versionRef("exposed")
|
library("exposed-jdbc", "org.jetbrains.exposed", "exposed-jdbc").versionRef("exposed")
|
||||||
library("exposed-java-time", "org.jetbrains.exposed", "exposed-java-time").versionRef("exposed")
|
library("exposed-java-time", "org.jetbrains.exposed", "exposed-java-time").versionRef("exposed")
|
||||||
library("hikaricp", "com.zaxxer", "HikariCP").versionRef("hikaricp")
|
library("hikaricp", "com.zaxxer", "HikariCP").versionRef("hikaricp")
|
||||||
|
library("tailscale", "gay.pizza.tailscale", "tailscale").versionRef("libtailscale")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user