Skip to content

Commit

Permalink
Upstream proxy server support (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
krlvm committed Dec 18, 2020
1 parent f4bf499 commit 96f750c
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 8 deletions.
20 changes: 20 additions & 0 deletions app/src/main/java/ru/krlvm/powertunnel/PowerTunnel.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ru.krlvm.powertunnel;

import org.jitsi.dnssec.validator.ValidatingResolver;
import org.littleshoot.proxy.ChainedProxyManager;
import org.littleshoot.proxy.HttpFilters;
import org.littleshoot.proxy.HttpFiltersSourceAdapter;
import org.littleshoot.proxy.HttpProxyServer;
Expand All @@ -20,6 +21,7 @@

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpRequest;
import ru.krlvm.powertunnel.adapters.UpstreamChainedProxyAdapter;
import ru.krlvm.powertunnel.android.managers.PTManager;
import ru.krlvm.powertunnel.android.resolver.AndroidDohResolver;
import ru.krlvm.powertunnel.enums.SNITrick;
Expand Down Expand Up @@ -83,6 +85,12 @@ public class PowerTunnel {
private static final Set<String> GOVERNMENT_BLACKLIST = null; //= new HashSet<>();
private static final Set<String> ISP_STUB_LIST = null; //= new HashSet<>();

public static boolean UPSTREAM_PROXY_CACHE = false;
public static String UPSTREAM_PROXY_IP = null;
public static int UPSTREAM_PROXY_PORT = -1;
public static String UPSTREAM_PROXY_USERNAME = null;
public static String UPSTREAM_PROXY_PASSWORD = null;

/**
* PowerTunnel bootstrap
*/
Expand Down Expand Up @@ -171,6 +179,18 @@ public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerCont
throw new Exception("Failed to initialize MITM Manager for SNI tricks: " + ex.getMessage(), ex);
}
}

if(UPSTREAM_PROXY_IP != null) {
ChainedProxyManager manager;
if(UPSTREAM_PROXY_CACHE) {
final UpstreamChainedProxyAdapter adapter = new UpstreamChainedProxyAdapter();
manager = (httpRequest, queue) -> queue.add(adapter);
} else {
manager = (httpRequest, queue) -> queue.add(new UpstreamChainedProxyAdapter());
}
bootstrap.withName("Downstream").withChainProxyManager(manager);
}

SERVER = bootstrap.start();
RUNNING = true;
System.out.println("[.] Server started");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ru.krlvm.powertunnel.adapters;

import org.littleshoot.proxy.ChainedProxyAdapter;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import ru.krlvm.powertunnel.PowerTunnel;

public class UpstreamChainedProxyAdapter extends ChainedProxyAdapter {

private InetSocketAddress cachedAddress = null;

public UpstreamChainedProxyAdapter() {
if (PowerTunnel.UPSTREAM_PROXY_CACHE) {
try {
cachedAddress = getAddress();
} catch (UnknownHostException ex) {
System.out.println("[x] Failed to cache upstream proxy address: " + ex.getMessage());
ex.printStackTrace();
}
}
}

@Override
public InetSocketAddress getChainedProxyAddress() {
try {
return cachedAddress == null ? getAddress() : cachedAddress;
} catch (UnknownHostException ex) {
System.out.println("[x] Failed to resolve upstream proxy address: " + ex.getMessage());
ex.printStackTrace();
return null;
}
}

private InetSocketAddress getAddress() throws UnknownHostException {
return new InetSocketAddress(InetAddress.getByName(PowerTunnel.UPSTREAM_PROXY_IP), PowerTunnel.UPSTREAM_PROXY_PORT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class MainActivity extends AppCompatActivity {
private Button start;
private Handler statusHandler = new Handler();
private Handler progressHandler = new Handler();
private static final long PROGRESS_DELAY = 500L;

private Tun2HttpVpnService service;
private ServiceConnection serviceConnection = new ServiceConnection() {
Expand Down Expand Up @@ -292,14 +293,14 @@ private void startTunnel() {
dialog.show();
updateStatus();
final boolean vpn = PTManager.isVPN(this);
progressHandler.post(() -> {
progressHandler.postDelayed(() -> {
if(vpn) {
startVpn();
} else {
startProxy();
}
dialog.dismiss();
});
}, PROGRESS_DELAY);
}

private void startVpn() {
Expand Down Expand Up @@ -337,10 +338,10 @@ private void stopTunnel() {
final ProgressDialog dialog = progress(false);
dialog.show();
updateStatus();
progressHandler.post(() -> {
progressHandler.postDelayed(() -> {
PTManager.stopTunnel(this);
dialog.dismiss();
});
}, PROGRESS_DELAY);
}

private ProgressDialog progress(boolean starting) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,13 @@ public void onCreate(Bundle savedInstanceState) {
clearAllSelection.setOnPreferenceClickListener(this);
findPreference(RESET_CONNECTION_SETTINGS).setOnPreferenceClickListener(this);
findPreference("theme").setOnPreferenceChangeListener(this);
findPreference("proxy_mode").setOnPreferenceChangeListener(this);
findPreference("sni").setOnPreferenceChangeListener(this);

findPreference("proxy_mode").setOnPreferenceChangeListener(this);
findPreference("upstream_proxy").setOnPreferenceChangeListener(this);

updateProxyVpn(!prefs.getBoolean("proxy_mode", false));
updateUpstreamProxy(prefs.getBoolean("upstream_proxy", false));

updateSpecDnsStatus(prefs.getString(DNS_PROVIDER, "GOOGLE_DOH"));
updateVPNModeItem();
Expand Down Expand Up @@ -130,6 +133,12 @@ private void updateProxyVpn(boolean vpnMode) {
updateVPNModeItem(vpnMode);
}

private void updateUpstreamProxy(boolean enabled) {
findPreference("upstream_ip").setEnabled(enabled);
findPreference("upstream_port").setEnabled(enabled);
findPreference("upstream_cache").setEnabled(enabled);
}

private void updateSpecDnsStatus(String provider) {
prefSpecDns.setEnabled(provider.equals("SPECIFIED"));
}
Expand Down Expand Up @@ -182,6 +191,7 @@ public boolean onPreferenceClick(Preference preference) {

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
System.out.println("CHANGED: " + preference.getKey());
switch (preference.getKey()) {
case "theme": {
MainActivity.applyTheme(((String) newValue));
Expand All @@ -195,6 +205,10 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
updateProxyVpn(vpnMode);
break;
}
case "upstream_proxy": {
updateUpstreamProxy(((boolean) newValue));
break;
}
case "sni": {
if(((boolean) newValue) && context != null) {
Toast.makeText(context, R.string.sni_warning, Toast.LENGTH_LONG).show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ public static void configure(Context context, SharedPreferences prefs) {
PowerTunnel.DEFAULT_CHUNK_SIZE = 2;
}
PowerTunnel.PAYLOAD_LENGTH = prefs.getBoolean("send_payload", false) ? 21 : 0;
if(prefs.getBoolean("upstream_proxy", false)) {
PowerTunnel.UPSTREAM_PROXY_CACHE = prefs.getBoolean("upstream_cache", false);
PowerTunnel.UPSTREAM_PROXY_IP = prefs.getString("upstream_ip", null);
PowerTunnel.UPSTREAM_PROXY_PORT = Integer.parseInt(prefs.getString("upstream_port", "-1"));
PowerTunnel.UPSTREAM_PROXY_USERNAME = prefs.getString("upstream_username", null);
PowerTunnel.UPSTREAM_PROXY_PASSWORD = prefs.getString("upstream_password", null);
} else {
PowerTunnel.UPSTREAM_PROXY_IP = null;
PowerTunnel.UPSTREAM_PROXY_USERNAME = null;
}
DNS_SERVERS = Util.getDefaultDNS(context);
DNS_OVERRIDE = false;
PowerTunnel.DOH_ADDRESS = null;
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,11 @@
<string name="read_more">Подробнее</string>
<string name="failed_to_start_powertunnel">Ошибка при запуске PowerTunnel</string>
<string name="restarting_proxy">Прокси-сервер перезапускается…</string>
<string name="pref_upstream_proxy">Подключаться используя внешний прокси-сервер</string>
<string name="pref_upstream_proxy_desc">Подключение к Интернету будет осуществляться через внешний прокси-сервер</string>
<string name="pref_upstream_ip">Адрес внешнего прокси-сервера</string>
<string name="pref_upstream_port">Порт внешнего прокси-сервера</string>
<string name="pref_upstream_title">Внешний прокси-сервер</string>
<string name="pref_upstream_cache">Кешировать адрес внешнего прокси-сервера</string>
<string name="pref_upstream_cache_desc">Увеличивает производительность</string>
</resources>
13 changes: 10 additions & 3 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@
<string name="dns_fetch_error">Failed to fetch the DNS servers list</string>
<string name="error">Error</string>
<string name="download">Download</string>
<string name="specify_dns_provider">Specify DNS provider</string>
<string name="specified_dns_provider">Specified DNS provider</string>
<string name="specify_dns_provider">Custom DNS provider</string>
<string name="specified_dns_provider">Custom DNS provider</string>
<string name="pref_theme_title">Dark theme</string>
<string name="pref_category_appearance">Appearance</string>
<string name="secdns_discounted">SecureDNS DNS provider has been discounted since April 30, 2020. Your DNS provider was automatically changed to CloudFlare DoH to avoid connectivity issues.</string>
Expand All @@ -130,7 +130,7 @@
<string name="proxy_mode_warning">Now you have to set applications proxy manually. If you have problems, switch back to VPN mode disabling proxy mode.</string>
<string name="notification_channel_proxy">PowerTunnel Proxy</string>
<string name="pref_category_vpn">VPN settings</string>
<string name="pref_proxy_ip">Local proxy server address</string>
<string name="pref_proxy_ip">Local proxy server IP address</string>
<string name="pref_proxy_port">Local proxy server port</string>
<string name="reset_connection_settings">Reset proxy settings</string>
<string name="reset_connection_settings_summary">Return to default address and port</string>
Expand All @@ -155,4 +155,11 @@
<string name="samsung_firmware_bug">Samsung introduced a bug in August 2020 software update that preventing us from starting VPN service, you have can solve this problem manually.</string>
<string name="read_more">Read more</string>
<string name="restarting_proxy">Restarting proxy server…</string>
<string name="pref_upstream_proxy">Connect via upstream proxy</string>
<string name="pref_upstream_proxy_desc">Use upstream proxy to connect to the Internet</string>
<string name="pref_upstream_ip">Upstream proxy IP address</string>
<string name="pref_upstream_port">Upstream proxy port</string>
<string name="pref_upstream_title">Upstream proxy</string>
<string name="pref_upstream_cache">Cache upstream proxy address</string>
<string name="pref_upstream_cache_desc">Improves performance</string>

This comment has been minimized.

Copy link
@DRSDavidSoft

DRSDavidSoft Dec 18, 2020

Maybe change this to "Do not resolve address on each request"?

This comment has been minimized.

Copy link
@krlvm

krlvm Dec 18, 2020

Author Owner

I agree

</resources>
30 changes: 30 additions & 0 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@
android:defaultValue="false"/>
</PreferenceCategory>

<PreferenceCategory android:title="@string/pref_upstream_title">
<SwitchPreference
android:title="@string/pref_upstream_proxy"
android:summary="@string/pref_upstream_proxy_desc"
android:key="upstream_proxy"
android:defaultValue="false"/>

<tun.proxy.preferences.preference.EditTextSummaryPreference
android:key="upstream_ip"
android:title="@string/pref_upstream_ip"
android:defaultValue=""
android:summary="%s"
app:useSimpleSummaryProvider="true" />

<tun.proxy.preferences.preference.EditTextSummaryPreference
android:key="upstream_port"
android:title="@string/pref_upstream_port"
android:defaultValue=""
android:summary="%s"
android:inputType="numberDecimal"
android:maxLength="4"
app:useSimpleSummaryProvider="true" />

<SwitchPreference
android:title="@string/pref_upstream_cache"
android:summary="@string/pref_upstream_cache_desc"
android:key="upstream_cache"
android:defaultValue="false"/>
</PreferenceCategory>

<PreferenceCategory android:title="@string/pref_category_vpn">
<ListPreference
android:key="vpn_connection_mode"
Expand Down

0 comments on commit 96f750c

Please sign in to comment.