diff --git a/daemons/import-export b/daemons/import-export
index 08674e7a0f885f1941cd4adcc109c71f647af16c..a3b778c7f04d925203bfc0ab858fe3adade02fdc 100755
--- a/daemons/import-export
+++ b/daemons/import-export
@@ -83,10 +83,12 @@ MIN_UPDATE_INTERVAL = 5.0
 #: Give child process up to 5 seconds to exit after sending a signal
 CHILD_LINGER_TIMEOUT = 5.0
 
+#: How long to wait for a connection to be established
+DEFAULT_CONNECT_TIMEOUT = 60
+
 # Common options for socat
 SOCAT_TCP_OPTS = ["keepalive", "keepidle=60", "keepintvl=10", "keepcnt=5"]
 SOCAT_OPENSSL_OPTS = ["verify=1", "cipher=HIGH", "method=TLSv1"]
-SOCAT_CONNECT_TIMEOUT = 60
 
 
 # Global variable for options
@@ -185,6 +187,12 @@ class StatusFile:
     """
     self._data.connected = True
 
+  def GetConnected(self):
+    """Determines whether the daemon is connected.
+
+    """
+    return self._data.connected
+
   def SetExitStatus(self, exit_status, error_message):
     """Sets the exit status and an error message.
 
@@ -237,10 +245,11 @@ def _ProcessSocatOutput(status_file, level, msg):
         status_file.SetListenPort(port)
         return True
 
-    m = TRANSFER_LOOP_RE.match(msg)
-    if m:
-      status_file.SetConnected()
-      return True
+    if not status_file.GetConnected():
+      m = TRANSFER_LOOP_RE.match(msg)
+      if m:
+        status_file.SetConnected()
+        return True
 
   return False
 
@@ -311,6 +320,11 @@ def GetSocatCommand(mode):
     addr1 = [
       "OPENSSL-LISTEN:%s" % port,
       "reuseaddr",
+
+      # Retry to listen if connection wasn't established successfully, up to
+      # 100 times a second. Note that this still leaves room for DoS attacks.
+      "forever",
+      "intervall=0.01",
       ] + common_addr_opts
     addr2 = ["stdout"]
 
@@ -318,7 +332,13 @@ def GetSocatCommand(mode):
     addr1 = ["stdin"]
     addr2 = [
       "OPENSSL:%s:%s" % (options.host, options.port),
-      "connect-timeout=%s" % SOCAT_CONNECT_TIMEOUT,
+
+      # How long to wait per connection attempt
+      "connect-timeout=%s" % options.connect_timeout,
+
+      # Retry a few times before giving up to connect (once per second)
+      "retry=%s" % options.connect_retries,
+      "intervall=1",
       ] + common_addr_opts
 
   else:
@@ -371,8 +391,6 @@ def GetTransportCommand(mode, socat_stderr_fd):
     raise Error("Invalid mode")
 
   # TODO: Use "dd" to measure processed data (allows to give an ETA)
-  # TODO: If a connection to socat is dropped (e.g. due to a wrong
-  # certificate), socat should be restarted
 
   # TODO: Run transport as separate user
   # The transport uses its own shell to simplify running it as a separate user
@@ -400,7 +418,7 @@ def GetCommand(mode, socat_stderr_fd):
 
 
 def ProcessChildIO(child, socat_stderr_read_fd, status_file, child_logger,
-                   signal_notify, signal_handler):
+                   signal_notify, signal_handler, mode):
   """Handles the child processes' output.
 
   """
@@ -429,19 +447,38 @@ def ProcessChildIO(child, socat_stderr_read_fd, status_file, child_logger,
         utils.SetNonblockFlag(fd, True)
         poller.register(fd, select.POLLIN)
 
-      timeout_calculator = None
+      if options.connect_timeout and mode == constants.IEM_IMPORT:
+        listen_timeout = locking.RunningTimeout(options.connect_timeout, True)
+      else:
+        listen_timeout = None
+
+      exit_timeout = None
+
       while True:
         # Break out of loop if only signal notify FD is left
         if len(fdmap) == 1 and signal_notify.fileno() in fdmap:
           break
 
-        if timeout_calculator:
-          timeout = timeout_calculator.Remaining() * 1000
+        timeout = None
+
+        if listen_timeout and not exit_timeout:
+          if status_file.GetConnected():
+            listen_timeout = None
+          elif listen_timeout.Remaining() < 0:
+            logging.info("Child process didn't establish connection in time")
+            child.Kill(signal.SIGTERM)
+            exit_timeout = \
+              locking.RunningTimeout(CHILD_LINGER_TIMEOUT, True)
+            # Next block will calculate timeout
+          else:
+            # Not yet connected, check again in a second
+            timeout = 1000
+
+        if exit_timeout:
+          timeout = exit_timeout.Remaining() * 1000
           if timeout < 0:
             logging.info("Child process didn't exit in time")
             break
-        else:
-          timeout = None
 
         for fd, event in utils.RetryOnSignal(poller.poll, timeout):
           if event & (select.POLLIN | event & select.POLLPRI):
@@ -456,13 +493,13 @@ def ProcessChildIO(child, socat_stderr_read_fd, status_file, child_logger,
                 # Signal handling
                 if signal_handler.called:
                   signal_handler.Clear()
-                  if timeout_calculator:
+                  if exit_timeout:
                     logging.info("Child process still has about %0.2f seconds"
-                                 " to exit", timeout_calculator.Remaining())
+                                 " to exit", exit_timeout.Remaining())
                   else:
                     logging.info("Giving child process %0.2f seconds to exit",
                                  CHILD_LINGER_TIMEOUT)
-                    timeout_calculator = \
+                    exit_timeout = \
                       locking.RunningTimeout(CHILD_LINGER_TIMEOUT, True)
             else:
               poller.unregister(fd)
@@ -478,7 +515,7 @@ def ProcessChildIO(child, socat_stderr_read_fd, status_file, child_logger,
 
       # If there was a timeout calculator, we were waiting for the child to
       # finish, e.g. due to a signal
-      return not bool(timeout_calculator)
+      return not bool(exit_timeout)
     finally:
       socat_stderr_lines.close()
   finally:
@@ -510,6 +547,13 @@ def ParseOptions():
                     help="Remote hostname")
   parser.add_option("--port", dest="port", action="store", type="int",
                     help="Remote port")
+  parser.add_option("--connect-retries", dest="connect_retries", action="store",
+                    type="int", default=0,
+                    help=("How many times the connection should be retried"
+                          " (export only)"))
+  parser.add_option("--connect-timeout", dest="connect_timeout", action="store",
+                    type="int", default=DEFAULT_CONNECT_TIMEOUT,
+                    help="Timeout for connection to be established (seconds)")
   parser.add_option("--cmd-prefix", dest="cmd_prefix", action="store",
                     type="string", help="Command prefix")
   parser.add_option("--cmd-suffix", dest="cmd_suffix", action="store",
@@ -635,8 +679,8 @@ def main():
             utils.RetryOnSignal(os.close, socat_stderr_write_fd)
 
             if ProcessChildIO(child, socat_stderr_read_fd, status_file,
-                              child_logger, signal_wakeup,
-                              signal_handler):
+                              child_logger, signal_wakeup, signal_handler,
+                              mode):
               # The child closed all its file descriptors and there was no
               # signal
               # TODO: Implement timeout instead of waiting indefinitely
diff --git a/test/import-export_unittest.bash b/test/import-export_unittest.bash
index 3b992edc0734f474ac241483173c49f2b79f6bfc..58ab8122360436ef50217508e46410ff4b4720ab 100755
--- a/test/import-export_unittest.bash
+++ b/test/import-export_unittest.bash
@@ -23,7 +23,7 @@ set -o pipefail
 
 export PYTHON=${PYTHON:=python}
 
-impexpd="$PYTHON daemons/import-export"
+impexpd="$PYTHON daemons/import-export --connect-timeout=1 --connect-retries=1"
 
 # Add "-d" for debugging
 #impexpd+=' -d'