All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.io.github.tim06.xrayConfiguration.XrayConfiguration.kt Maven / Gradle / Ivy

package io.github.tim06.xrayConfiguration

import io.github.tim06.xrayConfiguration.api.Api
import io.github.tim06.xrayConfiguration.burstObservatory.BurstObservatoryObject
import io.github.tim06.xrayConfiguration.burstObservatory.PingConfigObject
import io.github.tim06.xrayConfiguration.dns.Dns
import io.github.tim06.xrayConfiguration.dns.DnsServer
import io.github.tim06.xrayConfiguration.fakedns.FakeDns
import io.github.tim06.xrayConfiguration.inbounds.Destination
import io.github.tim06.xrayConfiguration.inbounds.Inbound
import io.github.tim06.xrayConfiguration.inbounds.Sniffing
import io.github.tim06.xrayConfiguration.inbounds.settings.HttpInboundConfigurationObject
import io.github.tim06.xrayConfiguration.inbounds.settings.SocksInboundConfigurationObject
import io.github.tim06.xrayConfiguration.log.Log
import io.github.tim06.xrayConfiguration.log.LogLevel
import io.github.tim06.xrayConfiguration.metrics.Metrics
import io.github.tim06.xrayConfiguration.observatory.ObservatoryObject
import io.github.tim06.xrayConfiguration.outbounds.Outbound
import io.github.tim06.xrayConfiguration.outbounds.settings.*
import io.github.tim06.xrayConfiguration.policy.Policy
import io.github.tim06.xrayConfiguration.reverse.Reverse
import io.github.tim06.xrayConfiguration.routing.*
import io.github.tim06.xrayConfiguration.stats.Stats
import io.github.tim06.xrayConfiguration.transport.Transport
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString

@Serializable
data class XrayConfiguration(
    @SerialName("log")
    val log: Log? = null,
    @SerialName("api")
    val api: Api? = null,
    @SerialName("dns")
    val dns: Dns? = null,
    @SerialName("routing")
    val routing: Routing? = null,
    @SerialName("policy")
    val policy: Policy? = null,
    @SerialName("inbounds")
    val inbounds: List? = null,
    @SerialName("outbounds")
    val outbounds: List? = null,
    @SerialName("transport")
    val transport: Transport? = null,
    @SerialName("stats")
    val stats: Stats? = null,
    @SerialName("reverse")
    val reverse: Reverse? = null,
    @SerialName("fakedns")
    val fakedns: List? = null,
    @SerialName("metrics")
    val metrics: Metrics? = null,
    @SerialName("observatory")
    val observatory: ObservatoryObject? = null,
    @SerialName("burstObservatory")
    val burstObservatory: BurstObservatoryObject? = null,
) {

    fun raw(): String = json.encodeToString(this)

    fun domain(): String? {
        return when (val settings = outbounds?.firstOrNull()?.settings) {
            is ShadowsocksOutboundConfigurationObject -> {
                val server = settings.servers.firstOrNull()
                server?.run { "$address:$port" }
            }

            is TrojanOutboundConfigurationObject -> {
                val server = settings.servers.firstOrNull()
                server?.run { "$address:$port" }
            }

            is VlessOutboundConfigurationObject -> {
                val server = settings.vnext.firstOrNull()
                server?.run { "$address:$port" }
            }

            is VmessOutboundConfigurationObject -> {
                val server = settings.vnext.firstOrNull()
                server?.run { "$address:$port" }
            }

            else -> error("Unknown outbound configuration for take domain!")
        }
    }

    companion object {
        fun fromJson(jsonString: String): XrayConfiguration {
            return json.decodeFromString(jsonString)
        }

        fun XrayConfiguration.addMinimalSettings(): XrayConfiguration {
            val dnsServers = listOf(
                DnsServer.DirectDnsServer("1.1.1.1"),
            )

            val inbounds = listOf(
                Inbound(
                    listen = "127.0.0.1",
                    port = 10808,
                    protocol = Protocol.SOCKS,
                    settings = SocksInboundConfigurationObject(
                        auth = SocksInboundConfigurationObject.Auth.NOAUTH,
                        udp = true,
                        userLevel = 8
                    ),
                    sniffing = Sniffing(
                        destOverride = listOf(Destination.HTTP, Destination.TLS),
                        enabled = true,
                        routeOnly = false
                    ),
                    tag = "socks"
                ),
                Inbound(
                    listen = "127.0.0.1",
                    port = 10809,
                    protocol = Protocol.HTTP,
                    settings = HttpInboundConfigurationObject(
                        userLevel = 8
                    ),
                    tag = "http"
                )
            )

            val blackholeOutbound = Outbound(
                protocol = Protocol.BLACKHOLE,
                settings = BlackholeOutboundConfigurationObject(
                    response = BlackholeOutboundConfigurationObject.Response(
                        type = BlackholeOutboundConfigurationObject.Response.Type.HTTP
                    )
                ),
                tag = "block"
            )

            val balancerRule = Rule(
                inboundTag = listOf(
                    "socks",
                    "http"
                ),
                balancerTag = "balancer"
            )

            val isMultipleOutbounds = outbounds != null && outbounds.count() > 1
            val defaultRulesTag = if (isMultipleOutbounds) "direct" else "proxy"
            val routingDefaultRules = mutableListOf(
                Rule(
                    ip = listOf("77.88.8.8"),
                    outboundTag = defaultRulesTag,
                    port = "53"
                ),
                Rule(
                    ip = listOf("1.1.1.1"),
                    outboundTag = "proxy".takeIf { !isMultipleOutbounds },
                    balancerTag = "balancer".takeIf { isMultipleOutbounds },
                    port = "53"
                ),
                Rule(
                    domain = listOf("domain:googleapis.cn", "domain:gstatic.com"),
                    outboundTag = "proxy".takeIf { !isMultipleOutbounds },
                    balancerTag = "balancer".takeIf { isMultipleOutbounds },
                ),
                Rule(
                    network = Network.UDP,
                    outboundTag = "block",
                    port = "443"
                ),
                Rule(
                    ip = listOf("geoip:private"),
                    outboundTag = "direct"
                ),
                Rule(
                    domain = listOf(
                        "domain:dns.alidns.com",
                        "domain:doh.pub",
                        "domain:dot.pub",
                        "domain:doh.360.cn",
                        "domain:dot.360.cn",
                        "geosite:cn",
                        "geosite:geolocation-cn"
                    ),
                    outboundTag = "direct"
                ),
                Rule(
                    ip = listOf(
                        "223.5.5.5/32",
                        "223.6.6.6/32",
                        "2400:3200::1/128",
                        "2400:3200:baba::1/128",
                        "119.29.29.29/32",
                        "1.12.12.12/32",
                        "120.53.53.53/32",
                        "2402:4e00::/128",
                        "2402:4e00:1::/128",
                        "180.76.76.76/32",
                        "2400:da00::6666/128",
                        "114.114.114.114/32",
                        "114.114.115.115/32",
                        "180.184.1.1/32",
                        "180.184.2.2/32",
                        "101.226.4.6/32",
                        "218.30.118.6/32",
                        "123.125.81.6/32",
                        "140.207.198.6/32",
                        "geoip:cn"
                    ),
                    outboundTag = "direct"
                ),
                Rule(
                    port = "0-65535",
                    outboundTag = "proxy".takeIf { !isMultipleOutbounds },
                    balancerTag = "balancer".takeIf { isMultipleOutbounds },
                )
            ).apply {
                if (isMultipleOutbounds) {
                    add(balancerRule)
                }
            }

            val balancer = Balancer(
                tag = "balancer",
                selector = outbounds?.mapNotNull { it.tag } ?: emptyList(),
            )
            return copy(
                dns = Dns(
                    servers = dnsServers,
                    disableCache = true,
                ),
                inbounds = inbounds,
                outbounds = outbounds?.let { outbounds ->
                    val current = outbounds.toMutableList()
                    current.add(blackholeOutbound)
                    current
                } ?: listOf(blackholeOutbound),
                log = Log(level = LogLevel.Info),
                routing = routing?.let { routing ->
                    routing.copy(
                        domainStrategy = routing.domainStrategy ?: DomainStrategy.IPIfNonMatch,
                        rules = routing.rules?.let { current ->
                            val mutable = current.toMutableList()
                            mutable.addAll(routingDefaultRules)
                            mutable
                        } ?: routingDefaultRules
                    )
                } ?: Routing(
                    domainStrategy = DomainStrategy.IPIfNonMatch,
                    rules = routingDefaultRules,
                    balancers = listOf(balancer).takeIf { isMultipleOutbounds }
                ),
                burstObservatory = BurstObservatoryObject(
                    subjectSelector = listOf("outbound"),
                    pingConfig = PingConfigObject(
                        destination = "http://www.gstatic.com/generate_204",
                        interval = "20s",
                        connectivity = "",
                        timeout = "2s",
                        sampling = 3
                    )
                ).takeIf { isMultipleOutbounds }
            )
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy