diff --git a/.github/workflows/build-unsigned.yaml b/.github/workflows/build-unsigned.yaml
index ed983fbdbe9140303ee16e5317a6be4c5aa92540..8ccb00da60efeef3e339c244fba626cbb0e16ad5 100644
--- a/.github/workflows/build-unsigned.yaml
+++ b/.github/workflows/build-unsigned.yaml
@@ -1,9 +1,6 @@
 name: Build Unsigned
 on:
-  workflow_dispatch:
   push:
-    branches:
-      - main
     paths-ignore:
       - '.github/**'
       - '.idea/**'
@@ -13,8 +10,6 @@ on:
       - 'LICENSE'
       - 'NOTICE'
   pull_request:
-    branches:
-      - main
     paths-ignore:
       - '.github/**'
       - '.idea/**'
@@ -38,10 +33,8 @@ jobs:
       - name: Setup Go
         uses: actions/setup-go@v2
         with:
-          go-version: 1.16
+          go-version: 1.17
       - name: Setup Android SDK
         uses: android-actions/setup-android@v2
-      - name: Setup Cmake & Ninja
-        uses: lukka/get-cmake@latest
       - name: Build
-        run: ./gradlew --no-daemon app:assembleRelease
\ No newline at end of file
+        run: ./gradlew --no-daemon app:assembleFossRelease
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 7241312f919e354101f8c40eb549f7bebab6c1ef..4d69c5fc42d06fa982cf36d9f59ee8792ea2041c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,9 +19,11 @@ gradle-app.setting
 # Ignore IDEA config
 *.iml
 /.idea/*
-/core/src/main/golang/.idea/*
 !/.idea/codeStyles
-!/core/src/main/golang/.idea/codeStyles
+/core/src/foss/go/.idea/*
+!/core/src/foss/go/.idea/codeStyles
+/core/src/premium/go/.idea/*
+!/core/src/premium/go/.idea/codeStyles
 
 # KeyStore
 *.keystore
diff --git a/.gitmodules b/.gitmodules
index 3f087b14861bf4fb15da57da1d934fb978787ca9..923431b04b5f5be60835df165ee82bb9e49ff1ca 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,9 +1,3 @@
-[submodule "core/src/main/golang/clash"]
-	path = core/src/main/golang/clash
+[submodule "clash-foss"]
+	path = core/src/foss/go/clash
 	url = https://github.com/Kr328/clash.git
-[submodule "kaidl"]
-	path = kaidl
-	url = https://github.com/Kr328/kaidl.git
-[submodule "core/src/main/golang/tun2socket"]
-	path = core/src/main/golang/tun2socket
-	url = https://github.com/Kr328/tun2socket-lwip.git
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index c5b9e0586aa708d5191aa14edcb345674c291516..996fa576123e4af25d77418e100dabda307bdb58 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,144 +1,31 @@
-import java.util.*
-
 plugins {
-    id("com.android.application")
     kotlin("android")
     kotlin("kapt")
-}
-
-android {
-    compileSdk = buildTargetSdkVersion
-
-    flavorDimensions(buildFlavor)
-
-    defaultConfig {
-        applicationId = "com.github.kr328.clash"
-
-        minSdk = buildMinSdkVersion
-        targetSdk = buildTargetSdkVersion
-
-        versionCode = buildVersionCode
-        versionName = buildVersionName
-
-        resConfigs("zh-rCN", "zh-rHK", "zh-rTW")
-
-        resValue("string", "release_name", "v$buildVersionName")
-        resValue("integer", "release_code", "$buildVersionCode")
-    }
-
-    packagingOptions {
-        exclude("DebugProbesKt.bin")
-    }
-
-    buildTypes {
-        named("release") {
-            isMinifyEnabled = true
-            isShrinkResources = true
-            proguardFiles(
-                getDefaultProguardFile("proguard-android-optimize.txt"),
-                "proguard-rules.pro"
-            )
-        }
-    }
-
-    productFlavors {
-        create("foss") {
-            dimension = "foss"
-            versionNameSuffix = ".foss"
-            applicationIdSuffix = ".foss"
-        }
-        create("premium") {
-            dimension = "premium"
-            versionNameSuffix = ".premium"
-
-            if (buildFlavor == "premium") {
-                val localFile = rootProject.file("local.properties")
-                if (localFile.exists()) {
-                    val appCenterKey = localFile.inputStream()
-                        .use { Properties().apply { load(it) } }
-                        .getProperty("appcenter.key", null)
-
-                    if (appCenterKey != null) {
-                        buildConfigField("String", "APP_CENTER_KEY", "\"$appCenterKey\"")
-                    } else {
-                        buildConfigField("String", "APP_CENTER_KEY", "null")
-                    }
-                } else {
-                    buildConfigField("String", "APP_CENTER_KEY", "null")
-                }
-            }
-        }
-    }
-
-    val signingFile = rootProject.file("keystore.properties")
-    if (signingFile.exists()) {
-        val properties = Properties().apply {
-            signingFile.inputStream().use {
-                load(it)
-            }
-        }
-        signingConfigs {
-            create("release") {
-                storeFile = rootProject.file(properties.getProperty("storeFile")!!)
-                storePassword = properties.getProperty("storePassword")!!
-                keyAlias = properties.getProperty("keyAlias")!!
-                keyPassword = properties.getProperty("keyPassword")!!
-            }
-        }
-        buildTypes {
-            named("release") {
-                signingConfig = signingConfigs["release"]
-            }
-        }
-    }
-
-    buildFeatures {
-        dataBinding = true
-    }
-
-    compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_1_8
-        targetCompatibility = JavaVersion.VERSION_1_8
-    }
-
-    kotlinOptions {
-        jvmTarget = "1.8"
-    }
-
-    splits {
-        abi {
-            isEnable = true
-            isUniversalApk = true
-        }
-    }
+    id("com.android.application")
 }
 
 dependencies {
-    val premiumImplementation by configurations
+    implementation(project(":core"))
+    implementation(project(":service"))
+    implementation(project(":design"))
+    implementation(project(":common"))
 
-    api(project(":core"))
-    api(project(":service"))
-    api(project(":design"))
-    api(project(":common"))
+    implementation(kotlin("stdlib-jdk7"))
+    implementation(deps.kotlin.coroutine)
+    implementation(deps.androidx.core)
+    implementation(deps.androidx.activity)
+    implementation(deps.androidx.fragment)
+    implementation(deps.androidx.appcompat)
+    implementation(deps.androidx.coordinator)
+    implementation(deps.androidx.recyclerview)
+    implementation(deps.google.material)
 
-    premiumImplementation("com.microsoft.appcenter:appcenter-analytics:$appcenterVersion")
-    premiumImplementation("com.microsoft.appcenter:appcenter-crashes:$appcenterVersion")
+    val premiumImplementation by configurations
 
-    implementation(kotlin("stdlib-jdk7"))
-    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
-    implementation("androidx.core:core-ktx:$coreVersion")
-    implementation("androidx.activity:activity:$activityVersion")
-    implementation("androidx.appcompat:appcompat:$appcompatVersion")
-    implementation("androidx.coordinatorlayout:coordinatorlayout:$coordinatorlayoutVersion")
-    implementation("androidx.recyclerview:recyclerview:$recyclerviewVersion")
-    implementation("androidx.fragment:fragment:$fragmentVersion")
-    implementation("com.google.android.material:material:$materialVersion")
+    premiumImplementation(deps.appcenter.analytics)
+    premiumImplementation(deps.appcenter.crashes)
 }
 
-task("cleanRelease", type = Delete::class) {
+tasks.getByName("clean", type = Delete::class) {
     delete(file("release"))
 }
-
-afterEvaluate {
-    tasks["clean"].dependsOn(tasks["cleanRelease"])
-}
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 95b058a30cc44a9b45aae8f990e7b0b294cd5d14..f3ba5d7512ff8563d69c2b5377b7d912669bfaab 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,11 +1,127 @@
 @file:Suppress("UNUSED_VARIABLE")
 
+import com.android.build.gradle.BaseExtension
 import java.net.URL
 
+buildscript {
+    repositories {
+        mavenCentral()
+        mavenLocal()
+        google()
+        maven("https://maven.kr328.app/releases")
+    }
+    dependencies {
+        classpath(deps.build.android)
+        classpath(deps.build.kotlin.common)
+        classpath(deps.build.kotlin.serialization)
+        classpath(deps.build.ksp)
+        classpath(deps.build.golang)
+    }
+}
+
 allprojects {
     repositories {
         google()
         mavenCentral()
+        maven("https://maven.kr328.app/releases")
+    }
+}
+
+subprojects {
+    val isApp = name == "app"
+
+    apply(plugin = if (isApp) "com.android.application" else "com.android.library")
+
+    extensions.configure(BaseExtension::class) {
+        val minSdkVersion = 21
+        val targetSdkVersion = 30
+        val buildVersionCode = 204009
+        val buildVersionName = "2.4.9"
+        val defaultDimension = "feature"
+
+        ndkVersion = "23.0.7599858"
+
+        compileSdkVersion(targetSdkVersion)
+
+        defaultConfig {
+            if (isApp) {
+                applicationId = "com.github.kr328.clash"
+            }
+
+            minSdk = minSdkVersion
+            targetSdk = targetSdkVersion
+
+            versionName = buildVersionName
+            versionCode = buildVersionCode
+
+            if (!isApp) {
+                consumerProguardFiles("consumer-rules.pro")
+            }
+
+            resValue("string", "release_name", "v$buildVersionName")
+            resValue("integer", "release_code", "$buildVersionCode")
+
+            externalNativeBuild {
+                cmake {
+                    abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64")
+                }
+            }
+        }
+
+        externalNativeBuild {
+            cmake {
+                version = "3.18.1"
+            }
+        }
+
+        if (isApp) {
+            packagingOptions {
+                excludes.add("DebugProbesKt.bin")
+            }
+        }
+
+        buildTypes {
+            named("release") {
+                isMinifyEnabled = isApp
+                isShrinkResources = isApp
+                proguardFiles(
+                    getDefaultProguardFile("proguard-android-optimize.txt"),
+                    "proguard-rules.pro"
+                )
+            }
+        }
+
+        productFlavors {
+            flavorDimensions(defaultDimension)
+
+            create("foss") {
+                dimension = defaultDimension
+                versionNameSuffix = ".foss"
+
+                if (isApp) {
+                    applicationIdSuffix = ".foss"
+                }
+            }
+            create("premium") {
+                dimension = defaultDimension
+                versionNameSuffix = ".premium"
+            }
+        }
+
+        buildFeatures.apply {
+            dataBinding {
+                isEnabled = name != "hideapi"
+            }
+        }
+
+        if (isApp) {
+            splits {
+                abi {
+                    isEnable = true
+                    isUniversalApk = true
+                }
+            }
+        }
     }
 }
 
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
deleted file mode 100644
index 006b40066fcddeb0a6f14a57d50f35c50c3829f3..0000000000000000000000000000000000000000
--- a/buildSrc/build.gradle.kts
+++ /dev/null
@@ -1,25 +0,0 @@
-plugins {
-    kotlin("jvm") version "1.5.10"
-    `java-gradle-plugin`
-}
-
-repositories {
-    mavenCentral()
-    google()
-}
-
-dependencies {
-    implementation(kotlin("gradle-plugin"))
-    implementation(kotlin("serialization"))
-    implementation("com.android.tools.build:gradle:4.2.1")
-    implementation("com.google.devtools.ksp:symbol-processing-gradle-plugin:1.5.10-1.0.0-beta01")
-}
-
-gradlePlugin {
-    plugins {
-        create("golang") {
-            id = "clash-build"
-            implementationClass = "com.github.kr328.clash.tools.ClashBuildPlugin"
-        }
-    }
-}
diff --git a/buildSrc/src/main/java/Build.kt b/buildSrc/src/main/java/Build.kt
deleted file mode 100644
index 26fb8ad142e42a4ac22b15bc0f058bdec8fd9266..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/Build.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-import org.gradle.api.Project
-
-const val buildVersionCode = 204009
-const val buildVersionName = "2.4.9"
-
-const val buildMinSdkVersion = 21
-const val buildTargetSdkVersion = 30
-
-const val buildNdkVersion = "22.1.7171670"
-
-val Project.buildFlavor: String
-    get() {
-        return if (project(":core").file("src/main/golang/clash/script/script.go").exists())
-            "premium"
-        else
-            "foss"
-    }
\ No newline at end of file
diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt
deleted file mode 100644
index 4ecebf55ce0bca9e32ec2699581dcfd1491bc48d..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/Dependencies.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-const val activityVersion = "1.2.3"
-const val coroutineVersion = "1.5.0"
-const val roomVersion = "2.3.0"
-const val coreVersion = "1.5.0"
-const val appcompatVersion = "1.3.0"
-const val muiltprocessVersion = "1.0.0"
-const val appcenterVersion = "4.2.0"
-const val serializationVersion = "1.2.1"
-const val materialVersion = "1.3.0"
-const val coordinatorlayoutVersion = "1.1.0"
-const val recyclerviewVersion = "1.2.1"
-const val fragmentVersion = "1.3.4"
-const val viewpagerVersion = "1.0.0"
diff --git a/buildSrc/src/main/java/Files.kt b/buildSrc/src/main/java/Files.kt
deleted file mode 100644
index d870534f412025e869eec78b5c21c271ba88a824..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/Files.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-import org.gradle.api.Project
-import java.io.File
-
-val Project.golangSource: File
-    get() = file("src/main/golang")
-
-val Project.golangBuild: File
-    get() = buildDir.resolve("intermediates/golang")
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/BuildConfig.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/BuildConfig.kt
deleted file mode 100644
index 020cd442befa7b34ff192e851a3d617784dcda8a..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/BuildConfig.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.github.kr328.clash.tools
-
-import com.android.build.gradle.BaseExtension
-import com.android.build.gradle.api.BaseVariant
-import java.io.Serializable
-
-data class BuildConfig(
-    val debug: Boolean,
-    val premium: Boolean,
-    val abis: List<NativeAbi>,
-    val minSdkVersion: Int,
-) : Serializable {
-    companion object {
-        fun of(abis: List<NativeAbi>, minSdkVersion: Int, variant: BaseVariant): BuildConfig {
-            return BuildConfig(
-                debug = variant.buildType.isDebuggable,
-                premium = variant.flavorName == "premium",
-                abis = abis,
-                minSdkVersion = minSdkVersion
-            )
-        }
-    }
-}
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashBuildPlugin.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashBuildPlugin.kt
deleted file mode 100644
index 2bc69df97fc9168565593c6df20bd18d3ddd36fd..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashBuildPlugin.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.github.kr328.clash.tools
-
-import com.android.build.gradle.LibraryExtension
-import golangBuild
-import golangSource
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import java.util.*
-
-class ClashBuildPlugin : Plugin<Project> {
-    override fun apply(target: Project) {
-        target.afterEvaluate {
-            target.extensions.getByType(LibraryExtension::class.java).apply {
-                val abis = defaultConfig.externalNativeBuild.cmake.abiFilters
-                    .map { NativeAbi.parse(it) }
-                    .distinct()
-                val minSdkVersion = defaultConfig.minSdkVersion!!.apiLevel
-
-                target.tasks.register("cleanGolang", ClashCleanTask::class.java) {
-                    it.applyFrom(target, abis)
-
-                    target.tasks.getByName("clean").dependsOn(it)
-                }
-
-                libraryVariants.forEach { variant ->
-                    val config = BuildConfig.of(abis, minSdkVersion, variant)
-                    val buildDir = target.golangBuild.resolve(variant.name)
-                    val capitalize = variant.name.capitalize(Locale.getDefault())
-
-                    val task = target.tasks.register(
-                        "externalGolangBuild$capitalize",
-                        ClashBuildTask::class.java
-                    ) {
-                        it.config.set(config)
-                        it.ndkDirectory.set(ndkDirectory)
-                        it.inputDirectory.set(target.golangSource)
-                        it.outputDirectory.set(buildDir)
-                    }
-
-                    sourceSets.named(variant.name) {
-                        it.jniLibs {
-                            srcDir(buildDir)
-                        }
-                    }
-
-                    variant.externalNativeBuildProviders.forEach {
-                        it.get().dependsOn(task)
-                    }
-                    target.tasks.filter { it.name.startsWith("buildCMake") }.forEach {
-                        it.mustRunAfter(task)
-                    }
-                }
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashBuildTask.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashBuildTask.kt
deleted file mode 100644
index eb5aff5e9797dcd0a6fb0c99a99f2c44b86cb357..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashBuildTask.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.github.kr328.clash.tools
-
-import org.gradle.api.DefaultTask
-import org.gradle.api.file.DirectoryProperty
-import org.gradle.api.provider.Property
-import org.gradle.api.tasks.Input
-import org.gradle.api.tasks.InputDirectory
-import org.gradle.api.tasks.OutputDirectory
-import org.gradle.api.tasks.TaskAction
-import java.io.File
-
-abstract class ClashBuildTask : DefaultTask() {
-    abstract val config: Property<BuildConfig>
-        @Input get
-
-    abstract val ndkDirectory: DirectoryProperty
-        @InputDirectory get
-
-    abstract val inputDirectory: DirectoryProperty
-        @InputDirectory get
-
-    abstract val outputDirectory: DirectoryProperty
-        @OutputDirectory get
-
-    @TaskAction
-    fun build() {
-        val input = inputDirectory.file
-        val output = outputDirectory.file
-
-        val config = config.get()
-        val environment = Environment(ndkDirectory.file, config.minSdkVersion)
-
-        val tags = listOf("without_gvisor", "without_system") +
-                (if (config.debug) listOf("debug") else emptyList()) +
-                (if (config.premium) listOf("premium") else emptyList())
-
-        Command.ofGoModuleTidy(input).exec()
-
-        config.abis.forEach {
-            Command.ofGoRun(
-                "make/make.go",
-                listOf("tun2socket", ".", "android", it.goArch),
-                input.resolve("tun2socket"),
-                environment.ofLwipBuild(it)
-            ).exec()
-
-            Command.ofGoBuild(
-                "c-shared",
-                output.resolve("${it.value}/libclash.so"),
-                tags,
-                !config.debug,
-                input,
-                environment.ofCoreBuild(it)
-            ).exec()
-        }
-    }
-
-    private val DirectoryProperty.file: File
-        get() = get().asFile
-}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashCleanTask.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashCleanTask.kt
deleted file mode 100644
index 305dccca923944e6d61fc88249bc49ea3e0153b3..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/ClashCleanTask.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.github.kr328.clash.tools
-
-import org.gradle.api.Project
-import org.gradle.api.tasks.Delete
-import golangSource
-
-abstract class ClashCleanTask : Delete() {
-    fun applyFrom(project: Project, abis: List<NativeAbi>) {
-        val bridge = project.golangSource.resolve("tun2socket")
-
-        delete(bridge.resolve("build"))
-
-        abis.forEach {
-            delete(bridge.resolve("build_android_${it.goArch}.go"))
-        }
-    }
-}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/Command.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/Command.kt
deleted file mode 100644
index 625efb04693bd6b947488e355023cea97feb893e..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/Command.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.github.kr328.clash.tools
-
-import org.gradle.api.GradleException
-import java.io.File
-import kotlin.concurrent.thread
-
-class Command(
-    private val command: Array<String>,
-    workingDir: File,
-    environments: Map<String, String>
-) {
-    private val processBuilder: ProcessBuilder = ProcessBuilder(*command)
-        .redirectErrorStream(true)
-        .directory(workingDir)
-        .apply { environment().putAll(environments) }
-
-    fun exec() {
-        val process = processBuilder.start()
-
-        thread {
-            process.inputStream.copyTo(System.out)
-        }
-
-        val result = process.waitFor()
-
-        if (result != 0) {
-            throw GradleException("exec ${command.joinToString(" ")}: exit with $result")
-        }
-    }
-
-    companion object {
-        fun ofGoModuleTidy(workingDir: File): Command {
-            return Command(arrayOf("go", "mod", "tidy"), workingDir, System.getenv())
-        }
-
-        fun ofGoBuild(
-            mode: String,
-            output: File,
-            tags: List<String>,
-            strip: Boolean,
-            workingDir: File,
-            environments: Map<String, String>
-        ): Command {
-            val command = mutableListOf("go", "build")
-
-            // go build mode
-            command += "-buildmode"
-            command += mode
-
-            // output file
-            command += "-o"
-            command += output.absolutePath
-
-            // trim path prefix
-            command += "-trimpath"
-
-            if (tags.isNotEmpty()) {
-                command += "-tags"
-                command += tags.joinToString(",")
-            }
-
-            if (strip) {
-                command += "-ldflags"
-                command += "-s -w"
-            }
-
-            return Command(command.toTypedArray(), workingDir, environments)
-        }
-
-        fun ofGoRun(
-            file: String,
-            args: List<String>,
-            workingDir: File,
-            environments: Map<String, String>
-        ): Command {
-            val command = mutableListOf("go", "run")
-
-            command += file
-            command += args
-
-            return Command(command.toTypedArray(), workingDir, environments)
-        }
-    }
-}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/Environment.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/Environment.kt
deleted file mode 100644
index 0a026a3a4b803522721011b3ffdd025069817159..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/Environment.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.github.kr328.clash.tools
-
-import org.apache.tools.ant.taskdefs.condition.Os
-import org.gradle.api.GradleException
-import java.io.File
-
-class Environment(
-    private val ndkDirectory: File,
-    private val minSdkVersion: Int,
-) {
-    fun ofCoreBuild(abi: NativeAbi): Map<String, String> {
-        val host = when {
-            Os.isFamily(Os.FAMILY_WINDOWS) ->
-                "windows"
-            Os.isFamily(Os.FAMILY_MAC) ->
-                "darwin"
-            Os.isFamily(Os.FAMILY_UNIX) ->
-                "linux"
-            else ->
-                throw GradleException("Unsupported host: ${System.getProperty("os.name")}")
-        }
-
-        val compiler = ndkDirectory.resolve("toolchains/llvm/prebuilt/$host-x86_64/bin")
-            .resolve("${abi.compiler}${minSdkVersion}-clang")
-
-        return mapOf(
-            "CC" to compiler.absolutePath,
-            "GOOS" to "android",
-            "GOARCH" to abi.goArch,
-            "GOARM" to abi.goArm,
-            "CGO_ENABLED" to "1",
-            "CFLAGS" to "-O3 -Werror",
-        )
-    }
-
-    fun ofLwipBuild(abi: NativeAbi): Map<String, String> {
-        val host = when {
-            Os.isFamily(Os.FAMILY_WINDOWS) ->
-                "windows"
-            Os.isFamily(Os.FAMILY_MAC) ->
-                "darwin"
-            Os.isFamily(Os.FAMILY_UNIX) ->
-                "linux"
-            else ->
-                throw GradleException("Unsupported host: ${System.getProperty("os.name")}")
-        }
-
-        val compiler = ndkDirectory.resolve("toolchains/llvm/prebuilt/$host-x86_64/bin")
-            .resolve("${abi.compiler}${minSdkVersion}-clang")
-        val ar = ndkDirectory.resolve("toolchains/llvm/prebuilt/$host-x86_64/bin")
-            .resolve("${abi.archiver}-ar")
-
-        return mapOf(
-            "CC" to compiler.absolutePath,
-            "AR" to ar.absolutePath,
-        )
-    }
-}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/com/github/kr328/clash/tools/NativeAbi.kt b/buildSrc/src/main/java/com/github/kr328/clash/tools/NativeAbi.kt
deleted file mode 100644
index 029f17b657df613e967b8b5aaacba4c057e0c53d..0000000000000000000000000000000000000000
--- a/buildSrc/src/main/java/com/github/kr328/clash/tools/NativeAbi.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.github.kr328.clash.tools
-
-enum class NativeAbi(
-    val value: String,
-    val compiler: String,
-    val archiver: String,
-    val goArch: String,
-    val goArm: String
-) {
-    ArmeabiV7a("armeabi-v7a", "armv7a-linux-androideabi", "arm-linux-androideabi", "arm", "7"),
-    Arm64V8a("arm64-v8a", "aarch64-linux-android", "aarch64-linux-android", "arm64", ""),
-    X86("x86", "i686-linux-android", "i686-linux-android", "386", ""),
-    X64("x86_64", "x86_64-linux-android", "x86_64-linux-android", "amd64", "");
-
-    companion object {
-        fun parse(value: String): NativeAbi {
-            return when (value) {
-                ArmeabiV7a.value -> ArmeabiV7a
-                Arm64V8a.value -> Arm64V8a
-                X86.value -> X86
-                X64.value -> X64
-                else -> throw IllegalArgumentException("unsupported abi $value")
-            }
-        }
-    }
-}
diff --git a/common/build.gradle.kts b/common/build.gradle.kts
index 3b8e1e3404ce19e92fc7f65f6914484c42a2f20c..1d22fbd5c941b50fa241b368e51fe02b3113921a 100644
--- a/common/build.gradle.kts
+++ b/common/build.gradle.kts
@@ -1,50 +1,12 @@
 plugins {
-    id("com.android.library")
     kotlin("android")
-}
-
-android {
-    compileSdk = buildTargetSdkVersion
-
-    defaultConfig {
-        minSdk = buildMinSdkVersion
-        targetSdk = buildTargetSdkVersion
-
-        versionCode = buildVersionCode
-        versionName = buildVersionName
-
-        consumerProguardFiles("consumer-rules.pro")
-    }
-
-    buildTypes {
-        named("release") {
-            isMinifyEnabled = false
-            proguardFiles(
-                getDefaultProguardFile("proguard-android-optimize.txt"),
-                "proguard-rules.pro"
-            )
-        }
-    }
-
-    compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_1_8
-        targetCompatibility = JavaVersion.VERSION_1_8
-    }
-
-    kotlinOptions {
-        jvmTarget = "1.8"
-    }
+    id("com.android.library")
 }
 
 dependencies {
     compileOnly(project(":hideapi"))
 
     implementation(kotlin("stdlib-jdk7"))
-    implementation("androidx.core:core-ktx:$coreVersion")
-    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
-}
-
-repositories {
-    mavenCentral()
-    google()
+    implementation(deps.kotlin.coroutine)
+    implementation(deps.androidx.core)
 }
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index 2b67c88597f8c6bf6701573571778fdb92b00eaa..0dfdf937d3e8fe443e88b93350a0531b5da46f2e 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -1,12 +1,13 @@
+import com.github.kr328.golang.GolangPlugin
 import java.io.FileOutputStream
 import java.net.URL
 import java.time.Duration
 
 plugins {
-    id("com.android.library")
     kotlin("android")
+    id("com.android.library")
     id("kotlinx-serialization")
-    id("clash-build")
+    id("golang-android")
 }
 
 val geoipDatabaseUrl =
@@ -14,60 +15,31 @@ val geoipDatabaseUrl =
 val geoipInvalidate = Duration.ofDays(7)!!
 val geoipOutput = buildDir.resolve("intermediates/golang_blob")
 
-android {
-    compileSdk = buildTargetSdkVersion
-
-    ndkVersion = buildNdkVersion
-
-    flavorDimensions(buildFlavor)
-
-    defaultConfig {
-        minSdk = buildMinSdkVersion
-        targetSdk = buildTargetSdkVersion
-
-        versionCode = buildVersionCode
-        versionName = buildVersionName
-
-        consumerProguardFiles("consumer-rules.pro")
-
-        externalNativeBuild {
-            cmake {
-                abiFilters("arm64-v8a", "armeabi-v7a", "x86", "x86_64")
-                arguments(
-                    "-DGO_SOURCE:STRING=$golangSource",
-                    "-DGO_OUTPUT:STRING=$golangBuild",
-                    "-DFLAVOR_NAME=$buildFlavor",
-                )
-            }
-        }
-    }
-
-    buildTypes {
-        named("release") {
-            isMinifyEnabled = false
-            proguardFiles(
-                getDefaultProguardFile("proguard-android-optimize.txt"),
-                "proguard-rules.pro"
-            )
-        }
-    }
-
-    productFlavors {
+golang {
+    sourceSets {
         create("foss") {
-            dimension = "foss"
+            srcDir.set(file("src/foss/go"))
         }
         create("premium") {
-            dimension = "premium"
+            srcDir.set(file("src/premium/go"))
+        }
+        all {
+            fileName.set("libclash.so")
         }
     }
+}
 
-    compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_1_8
-        targetCompatibility = JavaVersion.VERSION_1_8
-    }
-
-    kotlinOptions {
-        jvmTarget = "1.8"
+android {
+    productFlavors {
+        all {
+            externalNativeBuild {
+                cmake {
+                    arguments("-DGO_SOURCE:STRING=${golang.sourceSets.getByName(name).srcDir.asFile.get()}")
+                    arguments("-DGO_OUTPUT:STRING=${GolangPlugin.outputDirOf(project, null, null)}")
+                    arguments("-DFLAVOR_NAME:STRING=$name")
+                }
+            }
+        }
     }
 
     externalNativeBuild {
@@ -78,12 +50,12 @@ android {
 }
 
 dependencies {
-    api(project(":common"))
+    implementation(project(":common"))
 
     implementation(kotlin("stdlib-jdk7"))
-    implementation("androidx.core:core-ktx:$coreVersion")
-    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
-    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
+    implementation(deps.androidx.core)
+    implementation(deps.kotlin.coroutine)
+    implementation(deps.kotlin.serialization.json)
 }
 
 repositories {
@@ -108,6 +80,8 @@ task("downloadGeoipDatabase") {
         var GeoipDatabase []byte
     """.trimIndent()
 
+    outputs.dir(geoipOutput)
+
     onlyIf {
         System.currentTimeMillis() - databaseFile.lastModified() > geoipInvalidate.toMillis()
     }
diff --git a/core/src/main/golang/.idea/codeStyles/Project.xml b/core/src/foss/go/.idea/codeStyles/Project.xml
similarity index 100%
rename from core/src/main/golang/.idea/codeStyles/Project.xml
rename to core/src/foss/go/.idea/codeStyles/Project.xml
diff --git a/core/src/main/golang/.idea/codeStyles/codeStyleConfig.xml b/core/src/foss/go/.idea/codeStyles/codeStyleConfig.xml
similarity index 100%
rename from core/src/main/golang/.idea/codeStyles/codeStyleConfig.xml
rename to core/src/foss/go/.idea/codeStyles/codeStyleConfig.xml
diff --git a/core/src/main/golang/app.go b/core/src/foss/go/app.go
similarity index 100%
rename from core/src/main/golang/app.go
rename to core/src/foss/go/app.go
diff --git a/core/src/main/golang/app/app.go b/core/src/foss/go/app/app.go
similarity index 100%
rename from core/src/main/golang/app/app.go
rename to core/src/foss/go/app/app.go
diff --git a/core/src/main/golang/app/content.go b/core/src/foss/go/app/content.go
similarity index 100%
rename from core/src/main/golang/app/content.go
rename to core/src/foss/go/app/content.go
diff --git a/core/src/main/golang/app/dns.go b/core/src/foss/go/app/dns.go
similarity index 100%
rename from core/src/main/golang/app/dns.go
rename to core/src/foss/go/app/dns.go
diff --git a/core/src/main/golang/app/tun.go b/core/src/foss/go/app/tun.go
similarity index 100%
rename from core/src/main/golang/app/tun.go
rename to core/src/foss/go/app/tun.go
diff --git a/core/src/main/golang/app/ui.go b/core/src/foss/go/app/ui.go
similarity index 100%
rename from core/src/main/golang/app/ui.go
rename to core/src/foss/go/app/ui.go
diff --git a/core/src/main/golang/bridge.c b/core/src/foss/go/bridge.c
similarity index 100%
rename from core/src/main/golang/bridge.c
rename to core/src/foss/go/bridge.c
diff --git a/core/src/main/golang/bridge.h b/core/src/foss/go/bridge.h
similarity index 100%
rename from core/src/main/golang/bridge.h
rename to core/src/foss/go/bridge.h
diff --git a/core/src/foss/go/clash b/core/src/foss/go/clash
new file mode 160000
index 0000000000000000000000000000000000000000..a918699140e9169f76600f2e7837ec6d69957fb5
--- /dev/null
+++ b/core/src/foss/go/clash
@@ -0,0 +1 @@
+Subproject commit a918699140e9169f76600f2e7837ec6d69957fb5
diff --git a/core/src/main/golang/common/path.go b/core/src/foss/go/common/path.go
similarity index 100%
rename from core/src/main/golang/common/path.go
rename to core/src/foss/go/common/path.go
diff --git a/core/src/main/golang/config.go b/core/src/foss/go/config.go
similarity index 100%
rename from core/src/main/golang/config.go
rename to core/src/foss/go/config.go
diff --git a/core/src/main/golang/config/defaults.go b/core/src/foss/go/config/defaults.go
similarity index 100%
rename from core/src/main/golang/config/defaults.go
rename to core/src/foss/go/config/defaults.go
diff --git a/core/src/main/golang/config/fetch.go b/core/src/foss/go/config/fetch.go
similarity index 100%
rename from core/src/main/golang/config/fetch.go
rename to core/src/foss/go/config/fetch.go
diff --git a/core/src/main/golang/config/load.go b/core/src/foss/go/config/load.go
similarity index 100%
rename from core/src/main/golang/config/load.go
rename to core/src/foss/go/config/load.go
diff --git a/core/src/main/golang/config/override.go b/core/src/foss/go/config/override.go
similarity index 100%
rename from core/src/main/golang/config/override.go
rename to core/src/foss/go/config/override.go
diff --git a/core/src/main/golang/config/process.go b/core/src/foss/go/config/process.go
similarity index 100%
rename from core/src/main/golang/config/process.go
rename to core/src/foss/go/config/process.go
diff --git a/core/src/main/golang/config/provider_open.go b/core/src/foss/go/config/provider_open.go
similarity index 82%
rename from core/src/main/golang/config/provider_open.go
rename to core/src/foss/go/config/provider_open.go
index 95bcebe3c5d7e30d28130b3acc668badaa84f2c1..b157ca31767328f45f1e45d1a05cf2254847fdc8 100644
--- a/core/src/main/golang/config/provider_open.go
+++ b/core/src/foss/go/config/provider_open.go
@@ -2,7 +2,11 @@
 
 package config
 
-import "github.com/Dreamacro/clash/config"
+import (
+	"io"
+
+	"github.com/Dreamacro/clash/config"
+)
 
 func forEachProviders(rawCfg *config.RawConfig, fun func(index int, total int, key string, provider map[string]interface{})) {
 	total := len(rawCfg.ProxyProvider)
@@ -17,6 +21,6 @@ func forEachProviders(rawCfg *config.RawConfig, fun func(index int, total int, k
 
 func destroyProviders(cfg *config.Config) {
 	for _, p := range cfg.Providers {
-		_ = p.Destroy()
+		_ = p.(io.Closer).Close()
 	}
 }
diff --git a/core/src/main/golang/config/provider_premium.go b/core/src/foss/go/config/provider_premium.go
similarity index 100%
rename from core/src/main/golang/config/provider_premium.go
rename to core/src/foss/go/config/provider_premium.go
diff --git a/core/src/main/golang/core/init.go b/core/src/foss/go/core/init.go
similarity index 62%
rename from core/src/main/golang/core/init.go
rename to core/src/foss/go/core/init.go
index 1f819ab1c6de2152e3ddf725a6986581c3edb04c..ccc38d1e8131e051efc19ee3f50dde858d26576d 100644
--- a/core/src/main/golang/core/init.go
+++ b/core/src/foss/go/core/init.go
@@ -2,7 +2,6 @@ package core
 
 import (
 	"errors"
-	"net"
 	"syscall"
 
 	"cfa/blob"
@@ -41,34 +40,13 @@ func Init(home, versionName string, platformVersion int) {
 		return pkg, nil
 	}
 
-	dialer.DialerHook = func(dialer *net.Dialer) error {
-		dialer.Control = func(network, address string, c syscall.RawConn) error {
-			return c.Control(func(fd uintptr) {
-				app.MarkSocket(int(fd))
-			})
-		}
-
-		return nil
-	}
-	dialer.ListenPacketHook = func(lc *net.ListenConfig, address string) (string, error) {
-		lc.Control = func(network, address string, c syscall.RawConn) error {
-			return c.Control(func(fd uintptr) {
-				app.MarkSocket(int(fd))
-			})
-		}
-
-		if platform.ShouldBlockConnection() {
-			return "", errBlocked
-		}
-
-		return address, nil
-	}
-
-	dialer.DialHook = func(dialer *net.Dialer, network string, ip net.IP) error {
+	dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error {
 		if platform.ShouldBlockConnection() {
 			return errBlocked
 		}
 
-		return nil
+		return conn.Control(func(fd uintptr) {
+			app.MarkSocket(int(fd))
+		})
 	}
 }
diff --git a/core/src/main/golang/debug.go b/core/src/foss/go/debug.go
similarity index 100%
rename from core/src/main/golang/debug.go
rename to core/src/foss/go/debug.go
diff --git a/core/src/main/golang/go.mod b/core/src/foss/go/go.mod
similarity index 74%
rename from core/src/main/golang/go.mod
rename to core/src/foss/go/go.mod
index 6fd8ca33e215b81fcc8ac0f72ffcb05a65fd2210..ff8b34762f2ca1b357e20991874740757fbe7d3b 100644
--- a/core/src/main/golang/go.mod
+++ b/core/src/foss/go/go.mod
@@ -6,8 +6,8 @@ require (
 	cfa/blob v0.0.0 // local generated
 	github.com/Dreamacro/clash v0.0.0 // local
 	github.com/dlclark/regexp2 v1.4.0
-	github.com/kr328/tun2socket v0.0.0 // local
-	github.com/miekg/dns v1.1.42
+	github.com/kr328/tun2socket-lwip v0.0.0-20210911023118-0b4947e2a9c1
+	github.com/miekg/dns v1.1.43
 	github.com/oschwald/geoip2-golang v1.5.0
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
 	gopkg.in/yaml.v2 v2.4.0
@@ -15,6 +15,4 @@ require (
 
 replace github.com/Dreamacro/clash => ./clash
 
-replace github.com/kr328/tun2socket => ./tun2socket
-
 replace cfa/blob => ../../../build/intermediates/golang_blob
diff --git a/core/src/foss/go/go.sum b/core/src/foss/go/go.sum
new file mode 100644
index 0000000000000000000000000000000000000000..3871057712840d281f35f40dd7bc3676fc54cc43
--- /dev/null
+++ b/core/src/foss/go/go.sum
@@ -0,0 +1,114 @@
+github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q=
+github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
+github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
+github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
+github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
+github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
+github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
+github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
+github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac h1:IO6EfdRnPhxgKOsk9DbewdtQZHKZKnGlW7QCUttvNys=
+github.com/insomniacslk/dhcp v0.0.0-20210827173440-b95caade3eac/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E=
+github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
+github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
+github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
+github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/kr328/tun2socket-lwip v0.0.0-20210911023118-0b4947e2a9c1 h1:NJ5NyPHIok6hqdELvrI4bps5lLyfJtFmm0K4c9CB/WM=
+github.com/kr328/tun2socket-lwip v0.0.0-20210911023118-0b4947e2a9c1/go.mod h1:JFkXLCpLkNVvLMRkq3gexTlRHfzbqcP5HfFOoq5Mj+g=
+github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
+github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
+github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
+github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
+github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
+github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
+github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
+github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
+github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
+github.com/oschwald/geoip2-golang v1.5.0 h1:igg2yQIrrcRccB1ytFXqBfOHCjXWIoMv85lVJ1ONZzw=
+github.com/oschwald/geoip2-golang v1.5.0/go.mod h1:xdvYt5xQzB8ORWFqPnqMwZpCpgNagttWdoZLlJQzg7s=
+github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
+github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA=
+github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
+go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg=
+golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI=
+golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/core/src/main/golang/log.go b/core/src/foss/go/log.go
similarity index 100%
rename from core/src/main/golang/log.go
rename to core/src/foss/go/log.go
diff --git a/core/src/main/golang/main.go b/core/src/foss/go/main.go
similarity index 100%
rename from core/src/main/golang/main.go
rename to core/src/foss/go/main.go
diff --git a/core/src/main/golang/platform/limit.go b/core/src/foss/go/platform/limit.go
similarity index 100%
rename from core/src/main/golang/platform/limit.go
rename to core/src/foss/go/platform/limit.go
diff --git a/core/src/main/golang/platform/procfs.go b/core/src/foss/go/platform/procfs.go
similarity index 100%
rename from core/src/main/golang/platform/procfs.go
rename to core/src/foss/go/platform/procfs.go
diff --git a/core/src/main/golang/proxy.go b/core/src/foss/go/proxy.go
similarity index 100%
rename from core/src/main/golang/proxy.go
rename to core/src/foss/go/proxy.go
diff --git a/core/src/main/golang/proxy/http.go b/core/src/foss/go/proxy/http.go
similarity index 100%
rename from core/src/main/golang/proxy/http.go
rename to core/src/foss/go/proxy/http.go
diff --git a/core/src/main/golang/trace.c b/core/src/foss/go/trace.c
similarity index 100%
rename from core/src/main/golang/trace.c
rename to core/src/foss/go/trace.c
diff --git a/core/src/main/golang/trace.h b/core/src/foss/go/trace.h
similarity index 100%
rename from core/src/main/golang/trace.h
rename to core/src/foss/go/trace.h
diff --git a/core/src/main/golang/tun.go b/core/src/foss/go/tun.go
similarity index 100%
rename from core/src/main/golang/tun.go
rename to core/src/foss/go/tun.go
diff --git a/core/src/main/golang/tun/dns.go b/core/src/foss/go/tun/dns.go
similarity index 100%
rename from core/src/main/golang/tun/dns.go
rename to core/src/foss/go/tun/dns.go
diff --git a/core/src/main/golang/tun/link.go b/core/src/foss/go/tun/link.go
similarity index 100%
rename from core/src/main/golang/tun/link.go
rename to core/src/foss/go/tun/link.go
diff --git a/core/src/main/golang/tun/tcp.go b/core/src/foss/go/tun/tcp.go
similarity index 98%
rename from core/src/main/golang/tun/tcp.go
rename to core/src/foss/go/tun/tcp.go
index 67976a1dc57099faa1f1df69de814bf63ad90fa4..1df0d2f06129343e64eac25d5bba7d035b46273a 100644
--- a/core/src/main/golang/tun/tcp.go
+++ b/core/src/foss/go/tun/tcp.go
@@ -46,7 +46,7 @@ accept:
 
 		metadata := &C.Metadata{
 			NetWork:    C.TCP,
-			Type:       C.SOCKS,
+			Type:       C.SOCKS5,
 			SrcIP:      sAddr.IP,
 			DstIP:      tAddr.IP,
 			SrcPort:    strconv.Itoa(sAddr.Port),
diff --git a/core/src/main/golang/tun/tun.go b/core/src/foss/go/tun/tun.go
similarity index 97%
rename from core/src/main/golang/tun/tun.go
rename to core/src/foss/go/tun/tun.go
index d6c3a7512a5503bbf444032504631b394d8b88e3..c6cef1ecaccbe735a425a6712b7e08acb0365964 100644
--- a/core/src/main/golang/tun/tun.go
+++ b/core/src/foss/go/tun/tun.go
@@ -7,7 +7,7 @@ import (
 	"sync"
 	"syscall"
 
-	"github.com/kr328/tun2socket"
+	"github.com/kr328/tun2socket-lwip"
 )
 
 type adapter struct {
diff --git a/core/src/main/golang/tun/udp.go b/core/src/foss/go/tun/udp.go
similarity index 96%
rename from core/src/main/golang/tun/udp.go
rename to core/src/foss/go/tun/udp.go
index 09c8f73fd420c0d22571428b13f9bb42c43e22b7..0389447d183ff53bcd3d3830d8b19d379f311b50 100644
--- a/core/src/main/golang/tun/udp.go
+++ b/core/src/foss/go/tun/udp.go
@@ -3,14 +3,14 @@ package tun
 import (
 	"net"
 
-	"github.com/Dreamacro/clash/log"
-	"github.com/Dreamacro/clash/transport/socks5"
-	"github.com/kr328/tun2socket"
-
 	"github.com/Dreamacro/clash/adapter/inbound"
 	"github.com/Dreamacro/clash/common/pool"
 	C "github.com/Dreamacro/clash/constant"
+	"github.com/Dreamacro/clash/log"
+	"github.com/Dreamacro/clash/transport/socks5"
 	"github.com/Dreamacro/clash/tunnel"
+
+	"github.com/kr328/tun2socket-lwip"
 )
 
 type packet struct {
@@ -74,7 +74,7 @@ read:
 			data:  buf[:n],
 		}
 
-		tunnel.UDPIn() <- inbound.NewPacket(socks5.ParseAddrToSocksAddr(tAddr), pkt, C.SOCKS)
+		tunnel.UDPIn() <- inbound.NewPacket(socks5.ParseAddrToSocksAddr(tAddr), pkt, C.SOCKS5)
 	}
 }
 
diff --git a/core/src/main/golang/tunnel.go b/core/src/foss/go/tunnel.go
similarity index 100%
rename from core/src/main/golang/tunnel.go
rename to core/src/foss/go/tunnel.go
diff --git a/core/src/main/golang/tunnel/conn.go b/core/src/foss/go/tunnel/conn.go
similarity index 100%
rename from core/src/main/golang/tunnel/conn.go
rename to core/src/foss/go/tunnel/conn.go
diff --git a/core/src/main/golang/tunnel/connectivity.go b/core/src/foss/go/tunnel/connectivity.go
similarity index 94%
rename from core/src/main/golang/tunnel/connectivity.go
rename to core/src/foss/go/tunnel/connectivity.go
index 76817310113d81fee7bb79aec2210afe6a6e4272..b79167beb9f1dd5a838eeeaa93416c6fb2f96bca 100644
--- a/core/src/main/golang/tunnel/connectivity.go
+++ b/core/src/foss/go/tunnel/connectivity.go
@@ -5,7 +5,7 @@ import (
 
 	"github.com/Dreamacro/clash/adapter"
 	"github.com/Dreamacro/clash/adapter/outboundgroup"
-	"github.com/Dreamacro/clash/adapter/provider"
+	"github.com/Dreamacro/clash/constant/provider"
 	"github.com/Dreamacro/clash/log"
 	"github.com/Dreamacro/clash/tunnel"
 )
diff --git a/core/src/main/golang/tunnel/geoip.go b/core/src/foss/go/tunnel/geoip.go
similarity index 100%
rename from core/src/main/golang/tunnel/geoip.go
rename to core/src/foss/go/tunnel/geoip.go
diff --git a/core/src/main/golang/tunnel/providers.go b/core/src/foss/go/tunnel/providers.go
similarity index 88%
rename from core/src/main/golang/tunnel/providers.go
rename to core/src/foss/go/tunnel/providers.go
index 86dbacde051ab8c5d4c1d67d586c32fa8256f8d4..e5dd95f01851d42b384cecb940110f724d8a0948 100644
--- a/core/src/main/golang/tunnel/providers.go
+++ b/core/src/foss/go/tunnel/providers.go
@@ -7,7 +7,8 @@ import (
 	"fmt"
 	"time"
 
-	"github.com/Dreamacro/clash/adapter/provider"
+	P "github.com/Dreamacro/clash/adapter/provider"
+	"github.com/Dreamacro/clash/constant/provider"
 	"github.com/Dreamacro/clash/tunnel"
 )
 
@@ -38,7 +39,7 @@ func QueryProviders() []*Provider {
 	for _, p := range providers {
 		updatedAt := time.Time{}
 
-		if s, ok := p.(provider.UpdatableProvider); ok {
+		if s, ok := p.(P.UpdatableProvider); ok {
 			updatedAt = s.UpdatedAt()
 		}
 
diff --git a/core/src/main/golang/tunnel/providers_premium.go b/core/src/foss/go/tunnel/providers_premium.go
similarity index 100%
rename from core/src/main/golang/tunnel/providers_premium.go
rename to core/src/foss/go/tunnel/providers_premium.go
diff --git a/core/src/main/golang/tunnel/proxies.go b/core/src/foss/go/tunnel/proxies.go
similarity index 98%
rename from core/src/main/golang/tunnel/proxies.go
rename to core/src/foss/go/tunnel/proxies.go
index d729f617475ae2da56bb3b9f754d76a1ab9c04ad..97d2c2d7b2dab726ee75babd075fef8ba1f6a9de 100644
--- a/core/src/main/golang/tunnel/proxies.go
+++ b/core/src/foss/go/tunnel/proxies.go
@@ -8,8 +8,8 @@ import (
 	"github.com/dlclark/regexp2"
 
 	"github.com/Dreamacro/clash/adapter/outboundgroup"
-	"github.com/Dreamacro/clash/adapter/provider"
 	C "github.com/Dreamacro/clash/constant"
+	"github.com/Dreamacro/clash/constant/provider"
 	"github.com/Dreamacro/clash/log"
 	"github.com/Dreamacro/clash/tunnel"
 )
diff --git a/core/src/main/golang/tunnel/state.go b/core/src/foss/go/tunnel/state.go
similarity index 100%
rename from core/src/main/golang/tunnel/state.go
rename to core/src/foss/go/tunnel/state.go
diff --git a/core/src/main/golang/tunnel/statistic.go b/core/src/foss/go/tunnel/statistic.go
similarity index 100%
rename from core/src/main/golang/tunnel/statistic.go
rename to core/src/foss/go/tunnel/statistic.go
diff --git a/core/src/main/golang/tunnel/suspend.go b/core/src/foss/go/tunnel/suspend.go
similarity index 100%
rename from core/src/main/golang/tunnel/suspend.go
rename to core/src/foss/go/tunnel/suspend.go
diff --git a/core/src/main/golang/utils.go b/core/src/foss/go/utils.go
similarity index 100%
rename from core/src/main/golang/utils.go
rename to core/src/foss/go/utils.go
diff --git a/core/src/main/cpp/CMakeLists.txt b/core/src/main/cpp/CMakeLists.txt
index f3fb5239783b0399ea74e102bef20075b9116f2b..3441d8bc24b4583dd86f0ac5466ef57cd47ebede 100644
--- a/core/src/main/cpp/CMakeLists.txt
+++ b/core/src/main/cpp/CMakeLists.txt
@@ -19,7 +19,6 @@ endif ()
 
 include_directories("${GO_OUTPUT_BASE}/${CMAKE_ANDROID_ARCH_ABI}")
 include_directories("${GO_SOURCE}")
-include_directories("${GO_SOURCE}/tun2socket/bridge/native")
 
 link_directories("${GO_OUTPUT_BASE}/${CMAKE_ANDROID_ARCH_ABI}")
 
diff --git a/core/src/main/golang/clash b/core/src/main/golang/clash
deleted file mode 160000
index 1f076a4724c7f0056d5a1a5bdd14d794aa635c81..0000000000000000000000000000000000000000
--- a/core/src/main/golang/clash
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 1f076a4724c7f0056d5a1a5bdd14d794aa635c81
diff --git a/core/src/main/golang/tun2socket b/core/src/main/golang/tun2socket
deleted file mode 160000
index ba5ce167b596e89b046376828c20778a8275f49c..0000000000000000000000000000000000000000
--- a/core/src/main/golang/tun2socket
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ba5ce167b596e89b046376828c20778a8275f49c
diff --git a/design/build.gradle.kts b/design/build.gradle.kts
index e664a2b4d831e6482eb90217a72cf03b5aa54680..f23bc6d25e15b87326f5a0c80864b4bda7761a7c 100644
--- a/design/build.gradle.kts
+++ b/design/build.gradle.kts
@@ -1,70 +1,22 @@
 plugins {
-    id("com.android.library")
     kotlin("android")
     kotlin("kapt")
-}
-
-android {
-    compileSdk = buildTargetSdkVersion
-
-    flavorDimensions(buildFlavor)
-
-    defaultConfig {
-        minSdk = buildMinSdkVersion
-        targetSdk = buildTargetSdkVersion
-
-        versionCode = buildVersionCode
-        versionName = buildVersionName
-
-        consumerProguardFiles("consumer-rules.pro")
-    }
-
-    buildTypes {
-        named("release") {
-            isMinifyEnabled = false
-            proguardFiles(
-                getDefaultProguardFile("proguard-android-optimize.txt"),
-                "proguard-rules.pro"
-            )
-        }
-    }
-
-    productFlavors {
-        create("foss") {
-            dimension = "foss"
-        }
-        create("premium") {
-            dimension = "premium"
-        }
-    }
-
-    buildFeatures {
-        dataBinding = true
-    }
-
-    compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_1_8
-        targetCompatibility = JavaVersion.VERSION_1_8
-    }
-
-    kotlinOptions {
-        jvmTarget = "1.8"
-    }
+    id("com.android.library")
 }
 
 dependencies {
-    api(project(":common"))
-    api(project(":core"))
-    api(project(":service"))
+    implementation(project(":common"))
+    implementation(project(":core"))
+    implementation(project(":service"))
 
     implementation(kotlin("stdlib-jdk7"))
-    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
-    implementation("androidx.core:core-ktx:$coreVersion")
-    implementation("androidx.appcompat:appcompat:$appcompatVersion")
-    implementation("androidx.activity:activity:$activityVersion")
-    implementation("com.google.android.material:material:$materialVersion")
-    implementation("androidx.coordinatorlayout:coordinatorlayout:$coordinatorlayoutVersion")
-    implementation("androidx.recyclerview:recyclerview:$recyclerviewVersion")
-    implementation("androidx.fragment:fragment:$fragmentVersion")
-    implementation("androidx.viewpager2:viewpager2:$viewpagerVersion")
+    implementation(deps.kotlin.coroutine)
+    implementation(deps.androidx.core)
+    implementation(deps.androidx.appcompat)
+    implementation(deps.androidx.activity)
+    implementation(deps.androidx.coordinator)
+    implementation(deps.androidx.recyclerview)
+    implementation(deps.androidx.fragment)
+    implementation(deps.androidx.viewpager)
+    implementation(deps.google.material)
 }
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index d64b2af96ee857243cfd877c052969faf275dcd2..1664ca00fe4528ce5c4d81fc37ad35d3d10bae55 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionSha256Sum=13bf8d3cf8eeeb5770d19741a59bde9bd966dd78d17f1bbad787a05ef19d1c2d
\ No newline at end of file
+distributionSha256Sum=a8da5b02437a60819cad23e10fc7e9cf32bcb57029d9cb277e26eeff76ce014b
\ No newline at end of file
diff --git a/gradlew b/gradlew
index 4f906e0c811fc9e230eb44819f509cd0627f2600..3da45c161b0b8e84c1a88711f3d98c3b22a28c42 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
 
 #
-# Copyright 2015 the original author or authors.
+# Copyright ? 2015-2021 the original authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
 #
 
 ##############################################################################
-##
-##  Gradle start up script for UN*X
-##
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions ?$var?, ?${var}?, ?${var:-default}?, ?${var+SET}?,
+#           ?${var#prefix}?, ?${var%suffix}?, and ?$( cmd )?;
+#         * compound commands having a testable exit status, especially ?case?;
+#         * various built-in commands including ?command?, ?set?, and ?ulimit?.
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
 ##############################################################################
 
 # Attempt to set APP_HOME
+
 # Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
 done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
 
 APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+APP_BASE_NAME=${0##*/}
 
 # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
 
 warn () {
     echo "$*"
-}
+} >&2
 
 die () {
     echo
     echo "$*"
     echo
     exit 1
-}
+} >&2
 
 # OS specific support (must be 'true' or 'false').
 cygwin=false
 msys=false
 darwin=false
 nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
 esac
 
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 if [ -n "$JAVA_HOME" ] ; then
     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
         # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
+        JAVACMD=$JAVA_HOME/jre/sh/java
     else
-        JAVACMD="$JAVA_HOME/bin/java"
+        JAVACMD=$JAVA_HOME/bin/java
     fi
     if [ ! -x "$JAVACMD" ] ; then
         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
 location of your Java installation."
     fi
 else
-    JAVACMD="java"
+    JAVACMD=java
     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 
 Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,95 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
 fi
 
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
 
 # For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
     # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
         fi
-        i=`expr $i + 1`
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
     done
-    case $i in
-        0) set -- ;;
-        1) set -- "$args0" ;;
-        2) set -- "$args0" "$args1" ;;
-        3) set -- "$args0" "$args1" "$args2" ;;
-        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
 fi
 
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
 
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
 
 exec "$JAVACMD" "$@"
diff --git a/hideapi/build.gradle.kts b/hideapi/build.gradle.kts
index d29bf1f248147ae224009fc4b119c3e6fc9a30d1..18008909b5df8f9adb755fe66a82ce49186bba46 100644
--- a/hideapi/build.gradle.kts
+++ b/hideapi/build.gradle.kts
@@ -1,31 +1,3 @@
 plugins {
     id("com.android.library")
 }
-
-android {
-    compileSdk = buildTargetSdkVersion
-
-    defaultConfig {
-        minSdk = buildMinSdkVersion
-        targetSdk = buildTargetSdkVersion
-
-        versionCode = buildVersionCode
-        versionName = buildVersionName
-
-        consumerProguardFiles("consumer-rules.pro")
-    }
-
-    buildTypes {
-        named("release") {
-            isMinifyEnabled = false
-            proguardFiles(
-                getDefaultProguardFile("proguard-android-optimize.txt"),
-                "proguard-rules.pro"
-            )
-        }
-    }
-}
-
-dependencies {
-
-}
\ No newline at end of file
diff --git a/kaidl b/kaidl
deleted file mode 160000
index 16da2e83b72eb6ce6088aac8b59e2735bf020e95..0000000000000000000000000000000000000000
--- a/kaidl
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 16da2e83b72eb6ce6088aac8b59e2735bf020e95
diff --git a/service/build.gradle.kts b/service/build.gradle.kts
index f4ecfe76abce74e6a0291699a2966c06a3beb446..38755d275a79457ac0740420d80365c6f8953a60 100644
--- a/service/build.gradle.kts
+++ b/service/build.gradle.kts
@@ -1,73 +1,26 @@
 plugins {
-    id("com.android.library")
     kotlin("android")
     kotlin("kapt")
     id("kotlinx-serialization")
+    id("com.android.library")
     id("com.google.devtools.ksp")
 }
 
-android {
-    compileSdk = buildTargetSdkVersion
-
-    flavorDimensions(buildFlavor)
-
-    defaultConfig {
-        minSdk = buildMinSdkVersion
-        targetSdk = buildTargetSdkVersion
-
-        versionCode = buildVersionCode
-        versionName = buildVersionName
-
-        consumerProguardFiles("consumer-rules.pro")
-    }
-
-    buildTypes {
-        named("release") {
-            isMinifyEnabled = false
-            proguardFiles(
-                getDefaultProguardFile("proguard-android-optimize.txt"),
-                "proguard-rules.pro"
-            )
-        }
-    }
-
-    productFlavors {
-        create("foss") {
-            dimension = "foss"
-        }
-        create("premium") {
-            dimension = "premium"
-        }
-    }
-
-    compileOptions {
-        sourceCompatibility = JavaVersion.VERSION_1_8
-        targetCompatibility = JavaVersion.VERSION_1_8
-    }
-
-    kotlinOptions {
-        jvmTarget = "1.8"
-    }
-}
-
 dependencies {
-    ksp(project(":kaidl:kaidl"))
-    kapt("androidx.room:room-compiler:$roomVersion")
+    ksp(deps.kaidl.compiler)
+    kapt(deps.androidx.room.compiler)
 
-    api(project(":core"))
-    api(project(":common"))
-
-    implementation(project(":kaidl:kaidl-runtime")) {
-        exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core")
-    }
+    implementation(project(":core"))
+    implementation(project(":common"))
 
     implementation(kotlin("stdlib-jdk7"))
-    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion")
-    implementation("androidx.room:room-runtime:$roomVersion")
-    implementation("androidx.room:room-ktx:$roomVersion")
-    implementation("androidx.core:core-ktx:$coreVersion")
-    implementation("dev.rikka.rikkax.preference:multiprocess:$muiltprocessVersion")
-    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
+    implementation(deps.kotlin.coroutine)
+    implementation(deps.kotlin.serialization.json)
+    implementation(deps.androidx.core)
+    implementation(deps.androidx.room.runtime)
+    implementation(deps.androidx.room.ktx)
+    implementation(deps.kaidl.runtime)
+    implementation(deps.rikkax.multiprocess)
 }
 
 afterEvaluate {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index a6f35485617e385bd5fe397c9fb5d4cf5cdd77c2..307ffdec96ca78868ac35e05065d0bdb8bffbed6 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,3 +1,7 @@
+@file:Suppress("UnstableApiUsage")
+
+enableFeaturePreview("VERSION_CATALOGS")
+
 rootProject.name = "ClashForAndroid"
 
 include(":app")
@@ -6,12 +10,52 @@ include(":service")
 include(":design")
 include(":common")
 include(":hideapi")
-include(":kaidl:kaidl")
-include(":kaidl:kaidl-runtime")
 
-pluginManagement {
-    repositories {
-        mavenCentral()
-        google()
+dependencyResolutionManagement {
+    versionCatalogs {
+        create("deps") {
+            val agp = "7.0.2"
+            val ksp = "1.5.30-1.0.0-beta09"
+            val kotlin = "1.5.30"
+            val golang = "1.0.1"
+            val coroutine = "1.5.0"
+            val coreKtx = "1.5.0"
+            val activity = "1.2.3"
+            val fragment = "1.3.4"
+            val appcompat = "1.3.0"
+            val coordinator = "1.1.0"
+            val recyclerview = "1.2.1"
+            val viewpager = "1.0.0"
+            val material = "1.3.0"
+            val appcenter = "4.2.0"
+            val serialization = "1.2.1"
+            val kaidl = "1.14"
+            val room = "2.3.0"
+            val multiprocess = "1.0.0"
+
+            alias("build-android").to("com.android.tools.build:gradle:$agp")
+            alias("build-kotlin-common").to("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin")
+            alias("build-kotlin-serialization").to("org.jetbrains.kotlin:kotlin-serialization:$kotlin")
+            alias("build-ksp").to("com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp")
+            alias("build-golang").to("com.github.kr328.golang:gradle-plugin:$golang")
+            alias("kotlin-coroutine").to("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine")
+            alias("kotlin-serialization-json").to("org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization")
+            alias("androidx-core").to("androidx.core:core-ktx:$coreKtx")
+            alias("androidx-activity").to("androidx.activity:activity:$activity")
+            alias("androidx-fragment").to("androidx.fragment:fragment:$fragment")
+            alias("androidx-appcompat").to("androidx.appcompat:appcompat:$appcompat")
+            alias("androidx-coordinator").to("androidx.coordinatorlayout:coordinatorlayout:$coordinator")
+            alias("androidx-recyclerview").to("androidx.recyclerview:recyclerview:$recyclerview")
+            alias("androidx-viewpager").to("androidx.viewpager2:viewpager2:$viewpager")
+            alias("androidx-room-compiler").to("androidx.room:room-compiler:$room")
+            alias("androidx-room-runtime").to("androidx.room:room-runtime:$room")
+            alias("androidx-room-ktx").to("androidx.room:room-ktx:$room")
+            alias("google-material").to("com.google.android.material:material:$material")
+            alias("appcenter-analytics").to("com.microsoft.appcenter:appcenter-analytics:$appcenter")
+            alias("appcenter-crashes").to("com.microsoft.appcenter:appcenter-crashes:$appcenter")
+            alias("kaidl-compiler").to("com.github.kr328.kaidl:kaidl:$kaidl")
+            alias("kaidl-runtime").to("com.github.kr328.kaidl:kaidl-runtime:$kaidl")
+            alias("rikkax-multiprocess").to("dev.rikka.rikkax.preference:multiprocess:$multiprocess")
+        }
     }
 }
\ No newline at end of file