Skip to content

Commit

Permalink
feat: 优化ip来源判断,支持CF CDN判断
Browse files Browse the repository at this point in the history
  • Loading branch information
Leon406 committed Aug 19, 2024
1 parent d764a83 commit c3b72bd
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 22 deletions.
16 changes: 8 additions & 8 deletions src/main/java/me/leon/GeoParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import com.maxmind.geoip2.DatabaseReader
import java.net.InetAddress
import me.leon.GeoParser.cityReader
import me.leon.GeoParser.countryReader
import me.leon.support.toFile
import me.leon.support.toInetAddress
import me.leon.support.*

object GeoParser {
// register at https://www.maxmind.com/, and download your file,you also can download from
// https://leon.lanzoui.com/i4XoWph8yaj
// register at https://www.maxmind.com/, and download your file
// todo change it to your own file
private const val geoDir = "C:/Users/Leon/Desktop/geo"
private val dbFile = "$geoDir/GeoLite2-City.mmdb".toFile()
Expand All @@ -30,16 +28,18 @@ fun String.ipCountryZh() =
runCatching { countryReader.country(this.toInetAddress()).country.names[CN] }
.getOrElse {
println("ipCountryZh error ${it.message}")
"未知"
}
ipInfo()
}?:ipInfo()

fun InetAddress.ipCountryZh() =
runCatching { countryReader.country(this).country.names[CN] }.getOrDefault("未知")

fun Sub.ipCountryZh(): String =
runCatching { countryReader.country(SERVER.toInetAddress()).country.names[CN] }
.getOrDefault("未知")
?: "未知"
.getOrDefault(SERVER.ipInfo())
?: SERVER.ipInfo()

private fun String.ipInfo() = "CF中转".takeIf { ipCloudFlare() }?:"未知"

fun String.ipCountryEn(): String =
runCatching { countryReader.country(this.toInetAddress()).country.isoCode }
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/me/leon/support/IpExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,57 @@ package me.leon.support

import java.net.InetAddress
import kotlin.jvm.Throws
import kotlin.math.pow

@Throws fun String.toInetAddress(): InetAddress = InetAddress.getByName(this)


val cfCidrs =
setOf(
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
"104.16.0.0/13",
"104.24.0.0/14",
"108.162.192.0/18",
"131.0.72.0/22",
"141.101.64.0/18",
"162.158.0.0/15",
"172.64.0.0/13",
"173.245.48.0/20",
"188.114.96.0/20",
"190.93.240.0/20",
"197.234.240.0/22",
"198.41.128.0/17"
)
.map { it.cidrRange() }

fun String.ip2Uint() = split(".").fold(0U) { acc, s -> acc * 256U + s.toUInt() }

fun UInt.toIp() = "${shr(24)}.${shr(16) and 0xFFU}.${shr(8) and 0xFFU}.${this and 0xFFU}"

fun String.ip2Binary() =
split(".")
.fold(StringBuilder()) { acc, s -> acc.append(s.toUInt().toString(2).padStart(8, '0')) }
.toString()

fun Int.ipMaskBinary() = "1".repeat(this) + "0".repeat(32 - this)

fun Int.ipMask() = ipMaskBinary().binary2Ip()

fun String.binary2Ip() = stripAllSpace().chunked(8).joinToString(".") { it.toUInt(2).toString() }

fun String.cidrRange(): UIntRange {
val (ipStr, cidrStr) = split("/").takeIf { it.size > 1 } ?: listOf(this, "24")
val cidr = cidrStr.takeIf { it.isNotEmpty() }?.toInt() ?: 24
val ip = ipStr.ip2Uint()
val sub = 32 - cidr
val count = 2.0.pow(sub).toInt()
val mask = cidr.ipMask().ip2Uint()
val net = mask and ip
return (net + 1U)..(net + (count - 2).toUInt())
}

fun String.ipCloudFlare() = cfCidrs.any { it.contains(ip2Uint()) }

fun String.stripAllSpace() = replace("\\s+".toRegex(), "")
Binary file modified src/main/resources/GeoLite2-Country.mmdb
Binary file not shown.
18 changes: 4 additions & 14 deletions src/test/java/me/leon/ip/GeoTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,12 @@ class GeoTest {
fun geoParse() {

val ipAddress = "128.101.101.101"

val response = cityReader.city(ipAddress.toInetAddress())
println(response)

response.country.run {
println("country isoCode: $isoCode name: $name name-zh: ${names["zh-CN"]}")
}
response.mostSpecificSubdivision.run {
println("subdivision isoCode: $isoCode name: $name name-zh: ${names["zh-CN"]}")
}
response.run { println("city: $city , postal: $postal location: $location") }
// val ipAddress = "104.19.45.161"

println(ipAddress.ipCountryZh())
println(ipAddress.ipCountryEn())
println(ipAddress.ipCityZh())
println(ipAddress.ipCountryEn())
// println(ipAddress.ipCountryEn())
// println(ipAddress.ipCityZh())
// println(ipAddress.ipCountryEn())
}

@Test
Expand Down

0 comments on commit c3b72bd

Please sign in to comment.