速狼加速器 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;
        }
    }
}