diff --git a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
index fea9959f62147b391a1c8efbbd768677ec551a5e..f34aa1bba4266b5360191e9eb42811f701478d47 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/NewsFetcher.java
@@ -36,6 +36,7 @@ import static net.i2p.update.UpdateMethod.*;
 import net.i2p.util.EepGet;
 import net.i2p.util.FileUtil;
 import net.i2p.util.Log;
+import net.i2p.util.PortMapper;
 import net.i2p.util.ReusableGZIPInputStream;
 import net.i2p.util.SecureFileOutputStream;
 import net.i2p.util.SSLEepGet;
@@ -82,6 +83,13 @@ class NewsFetcher extends UpdateRunner {
         boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS);
         String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
         int proxyPort = ConfigUpdateHandler.proxyPort(_context);
+        if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+            proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+            _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+            if (_log.shouldWarn())
+                _log.warn("Cannot fetch news - HTTP client tunnel not running");
+            return;
+        }
 
         for (URI uri : _urls) {
              _currentURI = uri;
diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java
index fe8bf2d11ac3c01492b87d3b6ffbe0721885b350..f69fcfe245c1990b51ba12e553daa9c139d92d79 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateChecker.java
@@ -3,11 +3,13 @@ package net.i2p.router.update;
 import java.io.File;
 import java.net.URI;
 import java.util.List;
+
 import net.i2p.crypto.TrustedUpdate;
 import net.i2p.router.RouterContext;
 import net.i2p.router.web.ConfigUpdateHandler;
 import net.i2p.update.*;
 import net.i2p.util.PartialEepGet;
+import net.i2p.util.PortMapper;
 
 /**
  * Check for an updated version of a plugin.
@@ -52,12 +54,22 @@ class PluginUpdateChecker extends UpdateRunner {
         protected void update() {
             // must be set for super
             _isPartial = true;
-            updateStatus("<b>" + _("Checking for update of plugin {0}", _appName) + "</b>");
             // use the same settings as for updater
             // always proxy, or else FIXME
             //boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
             String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
             int proxyPort = ConfigUpdateHandler.proxyPort(_context);
+            if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+                proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+                _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+                String msg = _("HTTP client proxy tunnel must be running");
+                if (_log.shouldWarn())
+                    _log.warn(msg);
+                updateStatus("<b>" + msg + "</b>");
+                _mgr.notifyCheckComplete(this, false, false);
+                return;
+            }
+            updateStatus("<b>" + _("Checking for update of plugin {0}", _appName) + "</b>");
             _baos.reset();
             try {
                 _get = new PartialEepGet(_context, proxyHost, proxyPort, _baos, _currentURI.toString(), TrustedUpdate.HEADER_BYTES);
diff --git a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java
index 9b7143ed52371b2cde6a40acd74e339307b8f976..0a58ba9f669396702dd4051898f59f02fde81df0 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/PluginUpdateRunner.java
@@ -26,6 +26,7 @@ import net.i2p.util.EepGet;
 import net.i2p.util.FileUtil;
 import net.i2p.util.Log;
 import net.i2p.util.OrderedProperties;
+import net.i2p.util.PortMapper;
 import net.i2p.util.SecureDirectory;
 import net.i2p.util.SecureFile;
 import net.i2p.util.VersionComparator;
@@ -98,11 +99,23 @@ class PluginUpdateRunner extends UpdateRunner {
                     }
                 }
             } else {
-                updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>");
                 // use the same settings as for updater
-                boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
+                //boolean shouldProxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
+                // always proxy, or else FIXME
+                boolean shouldProxy = true;
                 String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
                 int proxyPort = ConfigUpdateHandler.proxyPort(_context);
+                if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+                    proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+                    _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+                    String msg = _("HTTP client proxy tunnel must be running");
+                    if (_log.shouldWarn())
+                        _log.warn(msg);
+                    statusDone("<b>" + msg + "</b>");
+                    _mgr.notifyTaskFailed(this, msg, null);
+                    return;
+                }
+                updateStatus("<b>" + _("Downloading plugin from {0}", _xpi2pURL) + "</b>");
                 try {
                     if (shouldProxy)
                         // 10 retries!!
diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java
index 635d5d85ffba1e4532be30f15ef20492aaa39676..2024bacb1d3dfc1dc1ab1aa3755931bec3e075f5 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateChecker.java
@@ -8,6 +8,7 @@ import net.i2p.router.util.RFC822Date;
 import net.i2p.router.web.ConfigUpdateHandler;
 import net.i2p.update.*;
 import net.i2p.util.EepHead;
+import net.i2p.util.PortMapper;
 
 /**
  *  Does a simple EepHead to get the last-modified header.
@@ -55,6 +56,13 @@ class UnsignedUpdateChecker extends UpdateRunner {
         //boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
         String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
         int proxyPort = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT);
+        if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+            proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+            _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+            if (_log.shouldWarn())
+                _log.warn("Cannot check for unsigned update - HTTP client tunnel not running");
+            return false;
+        }
 
         try {
             EepHead get = new EepHead(_context, proxyHost, proxyPort, 0, url);
diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java
index 556d8b21a2383cf2b3a10e4ab1908593a572be0c..7a9519ff61909086e8e112a4e50c02cd1d99e648 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/UnsignedUpdateRunner.java
@@ -10,6 +10,7 @@ import net.i2p.router.web.ConfigUpdateHandler;
 import static net.i2p.update.UpdateType.*;
 import net.i2p.util.EepGet;
 import net.i2p.util.Log;
+import net.i2p.util.PortMapper;
 
     
 /**
@@ -30,13 +31,23 @@ class UnsignedUpdateRunner extends UpdateRunner {
         /** Get the file */
         @Override
         protected void update() {
-            String zipURL = _currentURI.toString();
-            if (_log.shouldLog(Log.DEBUG))
-                _log.debug("Starting unsigned update URL: " + zipURL);
             // always proxy for now
             //boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
             String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
             int proxyPort = ConfigUpdateHandler.proxyPort(_context);
+            if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+                proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+                _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+                String msg = _("HTTP client proxy tunnel must be running");
+                if (_log.shouldWarn())
+                    _log.warn(msg);
+                updateStatus("<b>" + msg + "</b>");
+                _mgr.notifyTaskFailed(this, msg, null);
+                return;
+            }
+            String zipURL = _currentURI.toString();
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("Starting unsigned update URL: " + zipURL);
             try {
                 // 40 retries!!
                 _get = new EepGet(_context, proxyHost, proxyPort, 40, _updateFile, zipURL, false);
diff --git a/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java b/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java
index 7417749ff40d651b17743b47f9feeeaa3adb31d6..682b9b447b527638e9be14de242e04957772f1bf 100644
--- a/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/update/UpdateRunner.java
@@ -16,6 +16,7 @@ import net.i2p.util.EepGet;
 import net.i2p.util.I2PAppThread;
 import net.i2p.util.Log;
 import net.i2p.util.PartialEepGet;
+import net.i2p.util.PortMapper;
 import net.i2p.util.SSLEepGet;
 import net.i2p.util.VersionComparator;
 
@@ -150,6 +151,16 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
             if (shouldProxy) {
                 proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
                 proxyPort = ConfigUpdateHandler.proxyPort(_context);
+                if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+                    proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+                    _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+                    String msg = _("HTTP client proxy tunnel must be running");
+                    if (_log.shouldWarn())
+                        _log.warn(msg);
+                    updateStatus("<b>" + msg + "</b>");
+                    _mgr.notifyTaskFailed(this, msg, null);
+                    return;
+                }
             } else {
                 // TODO, wrong method, fail
                 proxyHost = null;
@@ -170,9 +181,10 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
 
         if (_urls.isEmpty()) {
             // not likely, don't bother translating
-            updateStatus("<b>Update source list is empty, cannot download update</b>");
-            _log.error("Update source list is empty - cannot download update");
-            _mgr.notifyTaskFailed(this, "", null);
+            String msg = "Update source list is empty, cannot download update";
+            updateStatus("<b>" + msg + "</b>");
+            _log.error(msg);
+            _mgr.notifyTaskFailed(this, msg, null);
             return;
         }
 
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java
index dc0983ea297b373a7581a6b6da9a52d7a27e067c..605626211e9bb845aefc4de008bcf49d2812294f 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHandler.java
@@ -26,6 +26,7 @@ import net.i2p.router.startup.LoadClientAppsJob;
 import net.i2p.router.update.ConsoleUpdateManager;
 import static net.i2p.update.UpdateType.*;
 import net.i2p.util.SecureFileOutputStream;
+import net.i2p.util.PortMapper;
 
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 
@@ -490,6 +491,8 @@ public class ConfigClientsHandler extends FormHandler {
             addFormError(_("Plugin or update download already in progress."));
             return;
         }
+        if (!verifyProxy())
+            return;
         addFormNotice(_("Updating all plugins"));
         PluginStarter.updateAll(_context);
         // So that update() will post a status to the summary bar before we reload
@@ -500,6 +503,7 @@ public class ConfigClientsHandler extends FormHandler {
 
     /**
      *  @param app null for a new install
+     *  @param url http: or file:
      */
     private void installPlugin(String app, String url) {
         ConsoleUpdateManager mgr = UpdateHandler.updateManager(_context);
@@ -518,6 +522,10 @@ public class ConfigClientsHandler extends FormHandler {
             addFormError(_("Bad URL {0}", url));
             return;
         }
+        if (!url.startsWith("file:")) {
+            if (!verifyProxy())
+                return;
+        }
         if (mgr.installPlugin(app, uri)) {
             if (url.startsWith("file:"))
                 addFormNotice(_("Installing plugin from {0}", uri.getPath()));
@@ -538,6 +546,8 @@ public class ConfigClientsHandler extends FormHandler {
             addFormError("Update manager not registered, cannot check");
             return;
         }
+        if (!verifyProxy())
+            return;
         mgr.check(PLUGIN, app);
         addFormNotice(_("Checking plugin {0} for updates", app));
         // So that update() will post a status to the summary bar before we reload
@@ -546,6 +556,27 @@ public class ConfigClientsHandler extends FormHandler {
         } catch (InterruptedException ie) {}
     }
 
+    /**
+     *  Plugin checks, updates, and installs are always proxied.
+     *  See if the proxy tunnel is available, unless we're configured
+     *  to use something else (probably not).
+     *  Outputs form error if returning false.
+     *
+     *  @return true if available
+     *  @since 0.9.20
+     */
+    private boolean verifyProxy() {
+        String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
+        int proxyPort = ConfigUpdateHandler.proxyPort(_context);
+        boolean rv = !
+            (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+             proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+             _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0);
+        if (!rv)
+            addFormError(_("HTTP client proxy tunnel must be running"));
+        return rv;
+    }
+
     private void startPlugin(String app) {
         try {
             PluginStarter.startPlugin(_context, app);
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
index 3cd9adbf8f97340ccb53fb07d2929520104ec50f..134b727ef7652b2fe3f23a449f7efcfc16a503a2 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHandler.java
@@ -152,6 +152,17 @@ public class ConfigUpdateHandler extends FormHandler {
                 addFormError(_("Update or check already in progress"));
                 return;
             }
+
+            boolean shouldProxy = _context.getProperty(PROP_SHOULD_PROXY_NEWS, DEFAULT_SHOULD_PROXY_NEWS);
+            String proxyHost = _context.getProperty(PROP_PROXY_HOST, DEFAULT_PROXY_HOST);
+            int proxyPort = proxyPort(_context);
+            if (shouldProxy && proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+                proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+                _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+                addFormError(_("HTTP client proxy tunnel must be running"));
+                return;
+            }
+
             boolean a1 = mgr.checkAvailable(NEWS, 30*1000) != null;
             boolean a2 = false;
             if ((!a1) && _updateUnsigned && _zipURL != null && _zipURL.length() > 0)
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
index edcaf2f980d354d2ef007588bd30eef1bdc00a0f..ec10c0fce8949d5488b4cf021ad376dfd0a661a0 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/PluginStarter.java
@@ -32,6 +32,7 @@ import net.i2p.util.ConcurrentHashSet;
 import net.i2p.util.FileUtil;
 import net.i2p.util.I2PAppThread;
 import net.i2p.util.Log;
+import net.i2p.util.PortMapper;
 import net.i2p.util.SimpleTimer2;
 import net.i2p.util.Translate;
 import net.i2p.util.VersionComparator;
@@ -146,6 +147,17 @@ public class PluginStarter implements Runnable {
             } while (mgr.isUpdateInProgress(TYPE_DUMMY));
         }
 
+        String proxyHost = ctx.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
+        int proxyPort = ConfigUpdateHandler.proxyPort(ctx);
+        if (proxyPort == ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT &&
+            proxyHost.equals(ConfigUpdateHandler.DEFAULT_PROXY_HOST) &&
+            ctx.portMapper().getPort(PortMapper.SVC_HTTP_PROXY) < 0) {
+            mgr.notifyComplete(null, Messages.getString("Plugin update check failed", ctx) +
+                                     " - " +
+                                     Messages.getString("HTTP client proxy tunnel must be running", ctx));
+            return;
+        }
+
         Log log = ctx.logManager().getLog(PluginStarter.class);
         int updated = 0;
         for (Map.Entry<String, String> entry : toUpdate.entrySet()) {