fix some warning
This commit is contained in:
parent
4b1bae0e55
commit
5954894102
@ -44,12 +44,14 @@ class ARPTable(
|
|||||||
|
|
||||||
fun getMacFromIP(ip: Int): Pair<ByteArray?, Int> {
|
fun getMacFromIP(ip: Int): Pair<ByteArray?, Int> {
|
||||||
val gw = routeTable.getGateway(ip)
|
val gw = routeTable.getGateway(ip)
|
||||||
if (gw == null) {
|
if (gw == null || gw == 0) {
|
||||||
// not found in route table, just use the ip
|
// not found in route table, just use the ip
|
||||||
|
TerminalLogger.debugf { "ARP: IP=${ipToString(ip)} has no gateway (gw=$gw), querying IP directly." }
|
||||||
val value = content.get(ip)
|
val value = content.get(ip)
|
||||||
return Pair(value?.mac, ip)
|
return Pair(value?.mac, ip)
|
||||||
} else {
|
} else {
|
||||||
// gw not null, try find the gw's mac
|
// gw not null, try find the gw's mac
|
||||||
|
TerminalLogger.debugf { "ARP: IP=${ipToString(ip)} uses gateway=${ipToString(gw)}." }
|
||||||
val value = content.get(gw)
|
val value = content.get(gw)
|
||||||
return Pair(value?.mac, gw)
|
return Pair(value?.mac, gw)
|
||||||
}
|
}
|
||||||
@ -128,20 +130,14 @@ class ARPWaitList {
|
|||||||
// just skip the packet
|
// just skip the packet
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
TerminalLogger.debugf { "ARP resumed flow: ${describeIpv4Packet(item.originData)}" }
|
||||||
val packet = formEthernetPacket(node.mac.toByteArray(), mac.toByteArray(), item.originData)
|
val packet = formEthernetPacket(node.mac.toByteArray(), mac.toByteArray(), item.originData)
|
||||||
val size = packet.remaining()
|
val size = packet.remaining()
|
||||||
val encrypted = node.aes.encrypt(packet)
|
val packetBytes = ByteArray(size)
|
||||||
|
packet.get(packetBytes)
|
||||||
|
val encrypted = node.aes.encrypt(packetBytes)
|
||||||
if (encrypted != null) {
|
if (encrypted != null) {
|
||||||
val data = SDLData.newBuilder()
|
sendPacketToNet(node, mac, encrypted, size.toLong())
|
||||||
.setIsP2P(true)
|
|
||||||
.setNetworkId(networkid)
|
|
||||||
.setTtl(2)
|
|
||||||
.setSrcMac(node.mac)
|
|
||||||
.setDstMac(mac)
|
|
||||||
.setData(encrypted.toByteString())
|
|
||||||
.build()
|
|
||||||
val msg = encodeToUDPMessage(data, PacketType.Data)
|
|
||||||
sendPacketToNet(node, mac, msg, size.toLong())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import java.net.Inet4Address
|
|||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.ByteOrder
|
import java.nio.ByteOrder
|
||||||
import java.util.zip.CRC32
|
|
||||||
|
|
||||||
interface Iface {
|
interface Iface {
|
||||||
suspend fun doInit()
|
suspend fun doInit()
|
||||||
@ -101,24 +100,16 @@ interface IfaceTun: Iface {
|
|||||||
arp.dipaddr = arp.sipaddr
|
arp.dipaddr = arp.sipaddr
|
||||||
arp.sipaddr = node.deviceConfig.ip.netAddr
|
arp.sipaddr = node.deviceConfig.ip.netAddr
|
||||||
|
|
||||||
val bytes = arp.marshalToBytes()
|
val bytesBuf = arp.marshalToBytes()
|
||||||
val encrypted = node.aes.encrypt(bytes)
|
val bytesArr = ByteArray(bytesBuf.remaining())
|
||||||
|
bytesBuf.get(bytesArr)
|
||||||
|
val encrypted = node.aes.encrypt(bytesArr)
|
||||||
if (encrypted != null) {
|
if (encrypted != null) {
|
||||||
val dstmac = arp.dhwaddr.toByteString()
|
val dstmac = arp.dhwaddr.toByteString()
|
||||||
val data = SDLData.newBuilder()
|
|
||||||
.setIsP2P(true)
|
|
||||||
.setTtl(2)
|
|
||||||
.setNetworkId(node.networkID.get())
|
|
||||||
.setSrcMac(node.mac)
|
|
||||||
.setDstMac(dstmac)
|
|
||||||
.setData(encrypted.toByteString())
|
|
||||||
.build()
|
|
||||||
|
|
||||||
TerminalLogger.debugf {
|
TerminalLogger.debugf {
|
||||||
"send arp reply to ${macToString(dstmac)}"
|
"send arp reply to ${macToString(dstmac)}"
|
||||||
}
|
}
|
||||||
val content = encodeToUDPMessage(data, PacketType.Data)
|
sendPacketToNet(node, dstmac, encrypted, 0)
|
||||||
sendPacketToNet(node, dstmac, content, 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,17 +157,28 @@ interface IfaceTun: Iface {
|
|||||||
TerminalLogger.infof { "dropping tun packet due to not authed" }
|
TerminalLogger.infof { "dropping tun packet due to not authed" }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
val version = (data[0].toInt() ushr 4) and 0x0f
|
||||||
|
if (version != 4) {
|
||||||
|
TerminalLogger.debugf { "dropping non-IPv4 packet from tun: version=$version, bytes=${data.size}" }
|
||||||
|
return
|
||||||
|
}
|
||||||
val buffer = ByteBuffer.wrap(data, 12, 8).order(ByteOrder.BIG_ENDIAN)
|
val buffer = ByteBuffer.wrap(data, 12, 8).order(ByteOrder.BIG_ENDIAN)
|
||||||
val srcip = buffer.getInt()
|
val srcip = buffer.getInt()
|
||||||
val dstip = buffer.getInt()
|
val dstip = buffer.getInt()
|
||||||
|
|
||||||
TerminalLogger.debugf { "got ${data.size} bytes from tun" }
|
TerminalLogger.debugf { "got ${data.size} bytes from tun" }
|
||||||
|
TerminalLogger.debugf { "IPv4 flow from tun: ${describeIpv4Packet(data)}" }
|
||||||
|
|
||||||
if (!node.config.allowRouting && (srcip != node.deviceConfig.ip.netAddr)) {
|
if (!node.config.allowRouting && (srcip != node.deviceConfig.ip.netAddr)) {
|
||||||
TerminalLogger.infof { "dropping routed packet from tun" }
|
TerminalLogger.infof { "dropping routed packet from tun" }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.config.dropMulticast && (dstip.toUInt() shr 28) == 14u) {
|
||||||
|
TerminalLogger.debugf { "dropping multicast packet from tun: ${com.jihe.punchnet.sdlan.utils.ipToString(dstip)}" }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val (arpinfo, gwip) = arpTable.getMacFromIP(dstip)
|
val (arpinfo, gwip) = arpTable.getMacFromIP(dstip)
|
||||||
if (arpinfo == null) {
|
if (arpinfo == null) {
|
||||||
println("arp info is null")
|
println("arp info is null")
|
||||||
@ -190,27 +192,11 @@ interface IfaceTun: Iface {
|
|||||||
val buffer = arpinfo + node.mac.toByteArray() +
|
val buffer = arpinfo + node.mac.toByteArray() +
|
||||||
byteArrayOf((EtherType.IPV4.toInt() shr 8).toByte(), EtherType.IPV4.toByte()) +
|
byteArrayOf((EtherType.IPV4.toInt() shr 8).toByte(), EtherType.IPV4.toByte()) +
|
||||||
data
|
data
|
||||||
|
val size = buffer.size
|
||||||
val crc = CRC32()
|
val encrypted = node.aes.encrypt(buffer)
|
||||||
crc.update(buffer)
|
|
||||||
val cksum = ByteBuffer.allocate(4)
|
|
||||||
.putInt(crc.value.toInt())
|
|
||||||
.array()
|
|
||||||
val packet = buffer + cksum
|
|
||||||
val size = packet.size
|
|
||||||
val encrypted = node.aes.encrypt(packet)
|
|
||||||
if (encrypted != null) {
|
if (encrypted != null) {
|
||||||
val mac = arpinfo.toByteString()
|
val mac = arpinfo.toByteString()
|
||||||
val data = SDLData.newBuilder()
|
sendPacketToNet(node, mac, encrypted, size.toLong())
|
||||||
.setIsP2P(true)
|
|
||||||
.setNetworkId(node.networkID.get())
|
|
||||||
.setTtl(2)
|
|
||||||
.setSrcMac(node.mac)
|
|
||||||
.setDstMac(mac)
|
|
||||||
.setData(encrypted.toByteString())
|
|
||||||
.build()
|
|
||||||
val msg = encodeToUDPMessage(data, PacketType.Data)
|
|
||||||
sendPacketToNet(node, mac, msg, size.toLong())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,12 +103,19 @@ class RouteTable() {
|
|||||||
fun getGateway(ip: Int): Int? {
|
fun getGateway(ip: Int): Int? {
|
||||||
try {
|
try {
|
||||||
lock.readLock().lock()
|
lock.readLock().lock()
|
||||||
|
var bestGw: Int? = null
|
||||||
|
var bestMaskLen = -1
|
||||||
for (item in routeInfo) {
|
for (item in routeInfo) {
|
||||||
if ((ip and item.mask) == item.maskedAddr) {
|
if ((ip and item.mask) == item.maskedAddr) {
|
||||||
return item.gw
|
val maskLen = Integer.bitCount(item.mask)
|
||||||
|
if (maskLen > bestMaskLen) {
|
||||||
|
bestMaskLen = maskLen
|
||||||
|
bestGw = item.gw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
}
|
||||||
|
TerminalLogger.debugf { "RouteTable LPM: ip=${com.jihe.punchnet.sdlan.utils.ipToString(ip)} -> bestGw=${bestGw?.let { com.jihe.punchnet.sdlan.utils.ipToString(it) } ?: "null"} (maskLen=$bestMaskLen)" }
|
||||||
|
return bestGw
|
||||||
} finally {
|
} finally {
|
||||||
lock.readLock().unlock()
|
lock.readLock().unlock()
|
||||||
}
|
}
|
||||||
@ -122,11 +129,17 @@ class RouteTable2(
|
|||||||
val routeInfo: Array<RouteDetail> = initRouteInfo.toTypedArray()
|
val routeInfo: Array<RouteDetail> = initRouteInfo.toTypedArray()
|
||||||
|
|
||||||
fun getGeteway(ip: Int): Int? {
|
fun getGeteway(ip: Int): Int? {
|
||||||
|
var bestGw: Int? = null
|
||||||
|
var bestMaskLen = -1
|
||||||
for (item in routeInfo) {
|
for (item in routeInfo) {
|
||||||
if ((ip and item.mask) == item.maskedAddr) {
|
if ((ip and item.mask) == item.maskedAddr) {
|
||||||
return item.gw
|
val maskLen = Integer.bitCount(item.mask)
|
||||||
|
if (maskLen > bestMaskLen) {
|
||||||
|
bestMaskLen = maskLen
|
||||||
|
bestGw = item.gw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
}
|
||||||
|
return bestGw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,11 @@ package com.jihe.punchnet.sdlan.utils
|
|||||||
|
|
||||||
import com.jihe.punchnet.sdlan.config.AESConfig
|
import com.jihe.punchnet.sdlan.config.AESConfig
|
||||||
import com.jihe.punchnet.sdlan.logs.TerminalLogger
|
import com.jihe.punchnet.sdlan.logs.TerminalLogger
|
||||||
|
import org.bouncycastle.crypto.engines.ChaCha7539Engine
|
||||||
|
import org.bouncycastle.crypto.params.KeyParameter
|
||||||
|
import org.bouncycastle.crypto.params.ParametersWithIV
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
import javax.crypto.spec.IvParameterSpec
|
import javax.crypto.spec.IvParameterSpec
|
||||||
import javax.crypto.spec.SecretKeySpec
|
import javax.crypto.spec.SecretKeySpec
|
||||||
@ -10,6 +14,8 @@ import javax.crypto.spec.SecretKeySpec
|
|||||||
class AES private constructor () {
|
class AES private constructor () {
|
||||||
private var _secret: ByteArray = ByteArray(0)
|
private var _secret: ByteArray = ByteArray(0)
|
||||||
private var _iv: ByteArray = ByteArray(0)
|
private var _iv: ByteArray = ByteArray(0)
|
||||||
|
private var _algorithm: String = "aes"
|
||||||
|
private var _regionId: Long = 0
|
||||||
companion object {
|
companion object {
|
||||||
private var instance: AES? = null
|
private var instance: AES? = null
|
||||||
get() {
|
get() {
|
||||||
@ -29,13 +35,17 @@ class AES private constructor () {
|
|||||||
return _secret.size != 0
|
return _secret.size != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setSecret(secret: ByteArray?) {
|
fun setSecret(secret: ByteArray?, algorithm: String = "aes", regionId: Long = 0) {
|
||||||
if (secret == null) {
|
if (secret == null) {
|
||||||
_secret = ByteArray(0)
|
_secret = ByteArray(0)
|
||||||
_iv = ByteArray(0)
|
_iv = ByteArray(0)
|
||||||
|
_algorithm = "aes"
|
||||||
|
_regionId = 0
|
||||||
} else {
|
} else {
|
||||||
_secret = secret
|
_secret = secret
|
||||||
_iv = _secret.sliceArray(0..<16)
|
_iv = _secret.sliceArray(0..<16)
|
||||||
|
_algorithm = algorithm.lowercase()
|
||||||
|
_regionId = regionId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,14 +53,11 @@ class AES private constructor () {
|
|||||||
if (!isAuthorized()) {
|
if (!isAuthorized()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
|
|
||||||
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
|
|
||||||
try {
|
try {
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, keyspec, IvParameterSpec(_iv))
|
val input = ByteArray(content.remaining())
|
||||||
val output = ByteBuffer.allocate(cipher.getOutputSize(content.remaining()))
|
content.get(input)
|
||||||
cipher.doFinal(content, output)
|
val encrypted = encrypt(input) ?: return null
|
||||||
output.flip()
|
return ByteBuffer.wrap(encrypted)
|
||||||
return output
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println("failed to encrypt: ${e.toString()}")
|
println("failed to encrypt: ${e.toString()}")
|
||||||
return null
|
return null
|
||||||
@ -62,12 +69,15 @@ class AES private constructor () {
|
|||||||
TerminalLogger.errorf { "not authed, so not encrypting" }
|
TerminalLogger.errorf { "not authed, so not encrypting" }
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
|
|
||||||
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, keyspec, IvParameterSpec(_iv))
|
|
||||||
try {
|
try {
|
||||||
val encrypted = cipher.doFinal(content)
|
return when (_algorithm) {
|
||||||
return encrypted
|
"aes" -> aesCrypt(Cipher.ENCRYPT_MODE, content)
|
||||||
|
"chacha20" -> chacha20Crypt(content)
|
||||||
|
else -> {
|
||||||
|
TerminalLogger.errorf { "unsupported encryption algorithm: $_algorithm" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
TerminalLogger.errorf {"encrypt failed: $e"}
|
TerminalLogger.errorf {"encrypt failed: $e"}
|
||||||
return null
|
return null
|
||||||
@ -78,14 +88,11 @@ class AES private constructor () {
|
|||||||
if (!isAuthorized()) {
|
if (!isAuthorized()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
|
|
||||||
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, keyspec, IvParameterSpec(_iv))
|
|
||||||
try {
|
try {
|
||||||
val output = ByteBuffer.allocate(cipher.getOutputSize(ciphered.remaining()))
|
val input = ByteArray(ciphered.remaining())
|
||||||
cipher.doFinal(ciphered, output)
|
ciphered.get(input)
|
||||||
output.flip()
|
val decrypted = decrypt(input) ?: return null
|
||||||
return output
|
return ByteBuffer.wrap(decrypted)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@ -95,16 +102,40 @@ class AES private constructor () {
|
|||||||
if (!isAuthorized()) {
|
if (!isAuthorized()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
|
|
||||||
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, keyspec, IvParameterSpec(_iv))
|
|
||||||
try {
|
try {
|
||||||
val decrypted = cipher.doFinal(ciphered)
|
return when (_algorithm) {
|
||||||
return decrypted
|
"aes" -> aesCrypt(Cipher.DECRYPT_MODE, ciphered)
|
||||||
|
"chacha20" -> chacha20Crypt(ciphered)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun aesCrypt(mode: Int, content: ByteArray): ByteArray {
|
||||||
|
val cipher = Cipher.getInstance(AESConfig.CIPHER_ALGORITHM)
|
||||||
|
val keyspec = SecretKeySpec(_secret, AESConfig.KEY_SPEC)
|
||||||
|
cipher.init(mode, keyspec, IvParameterSpec(_iv))
|
||||||
|
return cipher.doFinal(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun chacha20Crypt(content: ByteArray): ByteArray {
|
||||||
|
val engine = ChaCha7539Engine()
|
||||||
|
val nonce = chacha20Nonce()
|
||||||
|
engine.init(true, ParametersWithIV(KeyParameter(_secret), nonce))
|
||||||
|
val output = ByteArray(content.size)
|
||||||
|
engine.processBytes(content, 0, content.size, output, 0)
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun chacha20Nonce(): ByteArray {
|
||||||
|
return ByteBuffer.allocate(12)
|
||||||
|
.order(ByteOrder.BIG_ENDIAN)
|
||||||
|
.putLong(0L)
|
||||||
|
.putInt(_regionId.toInt())
|
||||||
|
.array()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun byteArray2Hex(array: ByteArray): String {
|
fun byteArray2Hex(array: ByteArray): String {
|
||||||
|
|||||||
@ -109,7 +109,6 @@ class RSA private constructor () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pubkeyStr = pubFile.readText()
|
pubkeyStr = pubFile.readText()
|
||||||
println("pub key is ${pubkeyStr}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encrypt(input: ByteArray, use_private_key: Boolean = true): ByteArray {
|
fun encrypt(input: ByteArray, use_private_key: Boolean = true): ByteArray {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user