速狼加速器 v1.3.05版本的 MD5 值为:16b5e8af5c3774d85c1aa8bd4f624d0b
以下内容为反编译后的 DnsServerProxy.java 源代码,内容仅作参考
package com.lzz.youtu.VpnService;
import android.util.Log;
import androidx.work.PeriodicWorkRequest;
import com.lzz.youtu.ss.dns.DnsHeader;
import com.lzz.youtu.ss.tcpip.IPHeader;
import com.lzz.youtu.ss.tcpip.UDPHeader;
import com.lzz.youtu.tcp.util.CommonMethods;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class DnsServerProxy implements Runnable {
private static DnsServerProxy instance = new DnsServerProxy();
private ByteBuffer doMain = ByteBuffer.allocate(4096);
private ConcurrentHashMap<String, DnsInfo> domainIpMap;
private ConcurrentHashMap<String, DnsInfo> ipDomainMap;
private int ipIndex;
private ReentrantReadWriteLock mapLock;
private Lock readLock;
private Thread taskThread;
private Lock writeLock;
public DnsServerProxy() {
ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
this.mapLock = reentrantReadWriteLock;
this.readLock = reentrantReadWriteLock.readLock();
this.writeLock = this.mapLock.writeLock();
this.ipDomainMap = new ConcurrentHashMap<>();
this.domainIpMap = new ConcurrentHashMap<>();
}
public static DnsServerProxy getInstance() {
return instance;
}
public void init() {
this.ipIndex = 0;
Thread thread = new Thread(this);
this.taskThread = thread;
thread.start();
}
public void uninit() {
Thread thread = this.taskThread;
if (thread != null) {
thread.interrupt();
this.taskThread = null;
}
this.ipDomainMap.clear();
this.domainIpMap.clear();
this.ipIndex = 0;
}
private void buildIpHeader(byte[] bArr, int i, IPHeader iPHeader, int i2) {
IPHeader iPHeader2 = new IPHeader(bArr, i);
iPHeader2.setHeaderLength(20);
iPHeader2.setTos((byte) 0);
iPHeader2.setTotalLength(i2 + 20);
iPHeader2.setIdentification(4660);
iPHeader2.setFlagsAndOffset((short) 16384);
iPHeader2.setTTL((byte) 64);
iPHeader2.setProtocol((byte) 17);
iPHeader2.setCrc((short) 0);
iPHeader2.setSourceIP(iPHeader.getDestinationIP());
iPHeader2.setDestinationIP(iPHeader.getSourceIP());
iPHeader2.setCrc(CommonMethods.checksum(0L, bArr, i, 20));
}
private void buildDnsHeader(byte[] bArr, int i, DnsHeader dnsHeader, String str) {
DnsHeader dnsHeader2 = new DnsHeader(bArr, i);
dnsHeader2.setID(dnsHeader.getID());
dnsHeader2.setFlags((short) -32384);
dnsHeader2.setQuestionCount((short) 1);
dnsHeader2.setResourceCount((short) 1);
int i2 = 0;
dnsHeader2.setAResourceCount((short) 0);
dnsHeader2.setEResourceCount((short) 0);
int queriesDataLen = getQueriesDataLen(dnsHeader);
int i3 = 0;
while (i2 < queriesDataLen) {
dnsHeader2.Data[dnsHeader2.Offset + 12 + i3] = dnsHeader.Data[dnsHeader.Offset + 12 + i3];
i2++;
i3++;
}
CommonMethods.writeShort(dnsHeader2.Data, dnsHeader2.Offset + 12 + i3, (short) -16372);
int i4 = i3 + 2;
CommonMethods.writeShort(dnsHeader2.Data, dnsHeader2.Offset + 12 + i4, (short) 1);
int i5 = i4 + 2;
CommonMethods.writeShort(dnsHeader2.Data, dnsHeader2.Offset + 12 + i5, (short) 1);
int i6 = i5 + 2;
CommonMethods.writeInt(dnsHeader2.Data, dnsHeader2.Offset + 12 + i6, 600);
int i7 = i6 + 4;
CommonMethods.writeShort(dnsHeader2.Data, dnsHeader2.Offset + 12 + i7, (short) 4);
CommonMethods.writeInt(dnsHeader2.Data, dnsHeader2.Offset + 12 + i7 + 2, CommonMethods.ipStringToInt(str));
}
private void buildUdpHeader(byte[] bArr, int i, short s, short s2, int i2, IPHeader iPHeader, boolean z) {
UDPHeader uDPHeader = new UDPHeader(bArr, i);
uDPHeader.setSourcePort(s);
uDPHeader.setDestinationPort(s2);
int i3 = i2 + 8;
uDPHeader.setTotalLength(i3);
uDPHeader.setCrc((short) 0);
if (z) {
int i4 = i2 + 20;
byte[] bArr2 = new byte[i4];
CommonMethods.writeInt(bArr2, 0, iPHeader.getDestinationIP());
CommonMethods.writeInt(bArr2, 4, iPHeader.getSourceIP());
bArr2[8] = 0;
bArr2[9] = 17;
CommonMethods.writeShort(bArr2, 10, (short) i3);
System.arraycopy(bArr, i, bArr2, 12, i3);
uDPHeader.setCrc(CommonMethods.checksum(0L, bArr2, 0, i4));
}
}
private int getQueriesDataLen(DnsHeader dnsHeader) {
int i = 0;
while (dnsHeader.Data[dnsHeader.Offset + 12 + i] != 0) {
i++;
}
return i + 5;
}
private byte[] buildRespondPacket(IPHeader iPHeader, UDPHeader uDPHeader, DnsHeader dnsHeader, String str, String str2) {
int queriesDataLen = getQueriesDataLen(dnsHeader) + 12 + 12 + 4;
byte[] bArr = new byte[queriesDataLen + 28];
buildDnsHeader(bArr, 28, dnsHeader, str2);
buildUdpHeader(bArr, 20, uDPHeader.getDestinationPort(), uDPHeader.getSourcePort(), queriesDataLen, iPHeader, uDPHeader.getCrc() != 0);
buildIpHeader(bArr, 0, iPHeader, queriesDataLen + 8);
return bArr;
}
public String QueryIpWithDomain(String str) {
String str2;
this.readLock.lock();
DnsInfo dnsInfo = this.domainIpMap.get(str);
if (dnsInfo != null) {
dnsInfo.time = System.currentTimeMillis();
str2 = dnsInfo.ip;
} else {
str2 = null;
}
this.readLock.unlock();
return str2;
}
public String QueryDomainWithIp(String str) {
String str2;
this.readLock.lock();
DnsInfo dnsInfo = this.ipDomainMap.get(str);
if (dnsInfo != null) {
dnsInfo.time = System.currentTimeMillis();
str2 = dnsInfo.domain;
} else {
str2 = null;
}
this.readLock.unlock();
return str2;
}
private void insertMap(String str, String str2) {
DnsInfo dnsInfo = new DnsInfo(str2, str, System.currentTimeMillis());
this.writeLock.lock();
this.domainIpMap.put(str2, dnsInfo);
this.ipDomainMap.put(str, dnsInfo);
this.writeLock.unlock();
}
private String getNewIp() {
int ipStringToInt = CommonMethods.ipStringToInt("1.0.0.1");
int ipStringToInt2 = CommonMethods.ipStringToInt("126.255.255.254");
this.readLock.lock();
while (true) {
ConcurrentHashMap<String, DnsInfo> concurrentHashMap = this.ipDomainMap;
int i = this.ipIndex;
this.ipIndex = i + 1;
if (concurrentHashMap.get(CommonMethods.ipIntToString(i + ipStringToInt)) != null) {
if (this.ipIndex + ipStringToInt > ipStringToInt2) {
this.ipIndex = 0;
}
} else {
this.readLock.unlock();
return CommonMethods.ipIntToString((ipStringToInt + this.ipIndex) - 1);
}
}
}
public byte[] onDnsRequest(IPHeader iPHeader, UDPHeader uDPHeader, DnsHeader dnsHeader) {
String parseDnsProtocol = parseDnsProtocol(dnsHeader);
if (parseDnsProtocol == null) {
return null;
}
String QueryIpWithDomain = QueryIpWithDomain(parseDnsProtocol);
if (QueryIpWithDomain == null) {
QueryIpWithDomain = getNewIp();
insertMap(QueryIpWithDomain, parseDnsProtocol);
Log.d(getClass().getName(), "[onDnsRequest]: IP:" + QueryIpWithDomain + " domain:" + parseDnsProtocol);
}
return buildRespondPacket(iPHeader, uDPHeader, dnsHeader, parseDnsProtocol, QueryIpWithDomain);
}
private String parseDnsProtocol(DnsHeader dnsHeader) {
byte[] bArr = dnsHeader.Data;
int i = dnsHeader.Offset + 12;
Charset charset = StandardCharsets.UTF_8;
if (dnsHeader.Flags.QR || dnsHeader.QuestionCount <= 0) {
return null;
}
this.doMain.clear();
while (bArr[i] != 0) {
int i2 = i + 1;
byte b = bArr[i];
this.doMain.put(bArr, i2, b);
i = b + i2;
if (bArr[i] != 0) {
this.doMain.put((byte) 46);
}
}
if (((int) CommonMethods.readNumber(bArr, i + 1, 2)) != 1) {
return null;
}
this.doMain.flip();
return charset.decode(this.doMain).toString();
}
@Override
public void run() {
while (true) {
try {
synchronized (Thread.currentThread()) {
Thread.currentThread().wait(PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS);
}
long currentTimeMillis = System.currentTimeMillis();
this.writeLock.lock();
Iterator<Map.Entry<String, DnsInfo>> it2 = this.ipDomainMap.entrySet().iterator();
while (it2.hasNext()) {
DnsInfo value = it2.next().getValue();
if (currentTimeMillis - value.time > 600000) {
this.ipDomainMap.remove(value.ip);
this.domainIpMap.remove(value.domain);
}
}
this.writeLock.unlock();
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
public class DnsInfo {
private String domain;
private String ip;
private long time;
DnsInfo(String str, String str2, long j) {
this.domain = str;
this.ip = str2;
this.time = j;
}
}
}