Net Flex v版本的 MD5 值为:385c18cd288a0634841c2be4c516c1dd

以下内容为反编译后的 Tunnel.java 源代码,内容仅作参考


package com.romzkie.ultrasshservice.tunnel.vpn;

import android.content.Context;
import android.content.pm.PackageManager;
import android.net.VpnService;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import com.romzkie.ultrasshservice.SocksHttpService;
import com.romzkie.ultrasshservice.logger.SkStatus;
import com.romzkie.ultrasshservice.tunnel.vpn.NetworkSpace;
import com.romzkie.ultrasshservice.tunnel.vpn.Pdnsd;
import com.romzkie.ultrasshservice.tunnel.vpn.Tun2Socks;
import com.romzkie.ultrasshservice.tunnel.vpn.VpnUtils;
import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class Tunnel {
    private static final String DNS_RESOLVER_IP = "8.8.8.8";
    private static final int DNS_RESOLVER_PORT = 53;
    private static final String VPN_INTERFACE_NETMASK = "255.255.255.0";
    private static Tunnel mTunnel;
    private final HostService mHostService;
    private Pdnsd mPdnsd;
    private VpnUtils.PrivateAddress mPrivateAddress;
    private Tun2Socks mTun2Socks;
    private int mMtu = TunnelConstants.VPN_INTERFACE_MTU;
    private AtomicReference<ParcelFileDescriptor> mTunFd = new AtomicReference<>();
    private AtomicBoolean mRoutingThroughTunnel = new AtomicBoolean(false);
    private NetworkSpace mRoutes = new NetworkSpace();

    public interface HostService {
        String getAppName();

        Context getContext();

        Object getVpnService();

        Object newVpnServiceBuilder();

        void onDiagnosticMessage(String str);

        void onTunnelConnected();

        void onVpnEstablished();
    }

    public static synchronized Tunnel newTunnel(HostService hostService) {
        Tunnel tunnel;
        synchronized (Tunnel.class) {
            Tunnel tunnel2 = mTunnel;
            if (tunnel2 != null) {
                tunnel2.stop();
            }
            tunnel = new Tunnel(hostService);
            mTunnel = tunnel;
        }
        return tunnel;
    }

    private Tunnel(HostService hostService) {
        this.mHostService = hostService;
    }

    public Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }

    public synchronized boolean startRouting(TunnelVpnSettings tunnelVpnSettings) throws Exception {
        return startVpn(tunnelVpnSettings.mDnsForward, tunnelVpnSettings.mDnsResolver, tunnelVpnSettings.mExcludeIps, tunnelVpnSettings.mEnableFilterApps, tunnelVpnSettings.mFilterBypassMode, tunnelVpnSettings.mFilterApps, tunnelVpnSettings.mTetheringSubnet);
    }

    public synchronized boolean startTunneling(String str, String[] strArr, boolean z, String str2, boolean z2) throws Exception {
        return routeThroughTunnel(str, strArr, z, str2, z2);
    }

    public synchronized void stopTunneling() {
        stopRoutingThroughTunnel();
    }

    public synchronized void stop() {
        stopVpn();
    }

    private boolean startVpn(boolean z, String[] strArr, String[] strArr2, boolean z2, boolean z3, String[] strArr3, boolean z4) throws Exception {
        int i;
        String[] strArr4 = strArr;
        StringBuilder sb = new StringBuilder("Routes: ");
        StringBuilder sb2 = new StringBuilder("Routes Excluded: ");
        this.mPrivateAddress = VpnUtils.selectPrivateAddress();
        int length = strArr2.length;
        int i2 = 0;
        while (true) {
            i = 32;
            if (i2 >= length) {
                break;
            }
            this.mRoutes.addIP(new CIDRIP(strArr2[i2], 32), false);
            i2++;
        }
        Locale locale = Locale.getDefault();
        try {
            try {
                try {
                    Locale.setDefault(new Locale("en"));
                    VpnService.Builder addAddress = ((VpnService.Builder) this.mHostService.newVpnServiceBuilder()).addAddress(this.mPrivateAddress.mIpAddress, this.mPrivateAddress.mPrefixLength);
                    this.mRoutes.addIP(new CIDRIP("0.0.0.0", 0), true);
                    this.mRoutes.addIP(new CIDRIP("10.0.0.0", 8), false);
                    this.mRoutes.addIP(new CIDRIP(this.mPrivateAddress.mSubnet, this.mPrivateAddress.mPrefixLength), false);
                    if (z4) {
                        this.mRoutes.addIP(new CIDRIP("192.168.42.0", 23), false);
                        this.mRoutes.addIP(new CIDRIP("192.168.44.0", 24), false);
                        this.mRoutes.addIP(new CIDRIP("192.168.49.0", 24), false);
                    }
                    int length2 = strArr4.length;
                    int i3 = 0;
                    while (i3 < length2) {
                        String str = strArr4[i3];
                        try {
                            addAddress.addDnsServer(str);
                            try {
                                this.mRoutes.addIP(new CIDRIP(str, i), z);
                            } catch (IllegalArgumentException e) {
                                e = e;
                                this.mHostService.onDiagnosticMessage(String.format("Erro ao adicinar dns %s, %s", str, e.getLocalizedMessage()));
                                i3++;
                                strArr4 = strArr;
                                i = 32;
                            }
                        } catch (IllegalArgumentException e2) {
                            e = e2;
                        }
                        i3++;
                        strArr4 = strArr;
                        i = 32;
                    }
                    String str2 = Build.VERSION.RELEASE;
                    if (Build.VERSION.SDK_INT == 19 && !str2.startsWith("4.4.3") && !str2.startsWith("4.4.4") && !str2.startsWith("4.4.5") && !str2.startsWith("4.4.6") && this.mMtu < 1280) {
                        SkStatus.logInfo(String.format(Locale.US, "Forcing MTU to 1280 instead of %d to workaround Android Bug #70916", Integer.valueOf(this.mMtu)));
                        this.mMtu = 1280;
                    }
                    addAddress.setMtu(this.mMtu);
                    for (NetworkSpace.IpAddress ipAddress : this.mRoutes.getNetworks(true)) {
                        sb.append(String.format("%s/%d", ipAddress.getIPv4Address(), Integer.valueOf(ipAddress.networkMask)));
                        sb.append(", ");
                    }
                    sb.deleteCharAt(sb.lastIndexOf(", "));
                    for (NetworkSpace.IpAddress ipAddress2 : this.mRoutes.getNetworks(false)) {
                        sb2.append(String.format("%s/%d", ipAddress2.getIPv4Address(), Integer.valueOf(ipAddress2.networkMask)));
                        sb2.append(", ");
                    }
                    sb2.deleteCharAt(sb2.lastIndexOf(", "));
                    this.mHostService.onDiagnosticMessage(sb.toString());
                    this.mHostService.onDiagnosticMessage(sb2.toString());
                    NetworkSpace.IpAddress ipAddress3 = new NetworkSpace.IpAddress(new CIDRIP("224.0.0.0", 3), true);
                    for (NetworkSpace.IpAddress ipAddress4 : this.mRoutes.getPositiveIPList()) {
                        try {
                            if (ipAddress3.containsNet(ipAddress4)) {
                                SkStatus.logDebug("VPN: Ignoring multicast route: " + ipAddress4.toString());
                            } else {
                                addAddress.addRoute(ipAddress4.getIPv4Address(), ipAddress4.networkMask);
                            }
                        } catch (IllegalArgumentException e3) {
                            this.mHostService.onDiagnosticMessage("Route rejeitada: " + ipAddress4 + " " + e3.getLocalizedMessage());
                        }
                    }
                    if (Build.VERSION.SDK_INT >= 21 && z2) {
                        for (String str3 : strArr3) {
                            if (z3) {
                                try {
                                    addAddress.addDisallowedApplication(str3);
                                    this.mHostService.onDiagnosticMessage(String.format("Filtro de Apps: Vpn desativada para \"%s\"", str3));
                                } catch (PackageManager.NameNotFoundException unused) {
                                    this.mHostService.onDiagnosticMessage("Aplicativo \"" + str3 + "\" não encontrado. Filtro de Apps não irá funcionar, verifique as configurações.");
                                }
                            } else {
                                addAddress.addAllowedApplication(str3);
                                this.mHostService.onDiagnosticMessage(String.format("Filtro de Apps: Vpn ativada para \"%s\"", str3));
                            }
                        }
                    }
                    ParcelFileDescriptor establish = addAddress.setSession(this.mHostService.getAppName()).setConfigureIntent(SocksHttpService.getGraphPendingIntent(this.mHostService.getContext())).establish();
                    if (establish != null) {
                        this.mTunFd.set(establish);
                        this.mRoutingThroughTunnel.set(false);
                        this.mHostService.onVpnEstablished();
                        this.mRoutes.clear();
                        Locale.setDefault(locale);
                        return true;
                    }
                    Locale.setDefault(locale);
                    return false;
                } catch (Throwable th) {
                    Locale.setDefault(locale);
                    throw th;
                }
            } catch (IllegalArgumentException e4) {
                throw new Exception("startVpn failed", e4);
            }
        } catch (IllegalStateException e5) {
            throw new Exception("startVpn failed", e5);
        } catch (SecurityException e6) {
            throw new Exception("startVpn failed", e6);
        }
    }

    private boolean routeThroughTunnel(String str, String[] strArr, boolean z, String str2, boolean z2) {
        ParcelFileDescriptor parcelFileDescriptor;
        if (this.mRoutingThroughTunnel.compareAndSet(false, true) && (parcelFileDescriptor = this.mTunFd.get()) != null) {
            String str3 = null;
            if (z) {
                int findAvailablePort = VpnUtils.findAvailablePort(8091, 10);
                str3 = String.format("%s:%d", this.mPrivateAddress.mIpAddress, Integer.valueOf(findAvailablePort));
                Pdnsd pdnsd = new Pdnsd(this.mHostService.getContext(), strArr, 53, this.mPrivateAddress.mIpAddress, findAvailablePort);
                this.mPdnsd = pdnsd;
                pdnsd.setOnPdnsdListener(new Pdnsd.OnPdnsdListener() {
                    @Override
                    public void onStart() {
                        Tunnel.this.mHostService.onDiagnosticMessage("pdnsd started");
                    }

                    @Override
                    public void onStop() {
                        Tunnel.this.mHostService.onDiagnosticMessage("pdnsd stopped");
                        Tunnel.this.stop();
                    }
                });
                this.mPdnsd.start();
            }
            Tun2Socks tun2Socks = new Tun2Socks(this.mHostService.getContext(), parcelFileDescriptor, this.mMtu, this.mPrivateAddress.mRouter, "255.255.255.0", str, str2, str3, z2);
            this.mTun2Socks = tun2Socks;
            tun2Socks.setOnTun2SocksListener(new Tun2Socks.OnTun2SocksListener() {
                @Override
                public void onStart() {
                    Tunnel.this.mHostService.onDiagnosticMessage("tunnel core started");
                }

                @Override
                public void onStop() {
                    Tunnel.this.mHostService.onDiagnosticMessage("tunnel core stopped");
                    Tunnel.this.stop();
                }
            });
            this.mTun2Socks.start();
            this.mHostService.onTunnelConnected();
            this.mHostService.onDiagnosticMessage("routing through tunnel");
            return true;
        }
        return false;
    }

    private void stopRoutingThroughTunnel() {
        Tun2Socks tun2Socks = this.mTun2Socks;
        if (tun2Socks != null && tun2Socks.isAlive()) {
            this.mTun2Socks.interrupt();
        }
        this.mTun2Socks = null;
        Pdnsd pdnsd = this.mPdnsd;
        if (pdnsd != null && pdnsd.isAlive()) {
            this.mPdnsd.interrupt();
        }
        this.mPdnsd = null;
    }

    private void stopVpn() {
        stopRoutingThroughTunnel();
        ParcelFileDescriptor andSet = this.mTunFd.getAndSet(null);
        if (andSet != null) {
            try {
                this.mHostService.onDiagnosticMessage("VPN service stopped");
                andSet.close();
            } catch (IOException unused) {
            }
        }
    }
}