diff --git a/libtaskotron/remote_exec.py b/libtaskotron/remote_exec.py
--- a/libtaskotron/remote_exec.py
+++ b/libtaskotron/remote_exec.py
@@ -48,6 +48,9 @@
 class RemoteExec(object):
     '''Wrapper for SSH communication using paramiko library'''
 
+    # timeout for network operations in seconds (900 seconds = 15 minutes)
+    TIMEOUT = 900
+
     def __init__(self, hostname, port, username, key_filename, stdio_filename=None):
         self.ssh = None
         self.sftp = None
@@ -90,15 +93,15 @@
                              key_filename=self.key_filename or None)
 
             self.sftp = self.ssh.open_sftp()
+            self.sftp.get_channel().settimeout(self.TIMEOUT)
 
             if self.stdio_filename is not None:
                 try:
                     f = open(self.stdio_filename, 'w')
                     self.outstream.add(f)
                 except IOError, e:
                     log.warning('Could not open %s. Falling back to writing vm\'s output '
                                 'to stdout only.', self.stdio_filename)
-
         except paramiko.BadHostKeyException, e:
             raise exc.TaskotronRemoteError('Server\'s (%s@%s:%s) hostkey could not be verified: %s'
                                            % (self.username, self.hostname, self.port, str(e)))
@@ -126,23 +129,39 @@
         :param str cmd: A command to be executed
         :returns: returncode of the command
         :raise TaskotronRemoteError: If the command has non-zero return code and it isn't a code of
-                                     exitcode directive failure.
+                                     exitcode directive failure. Or if the remote hasn't sent any
+                                     data for ``TIMEOUT`` seconds.
         '''
 
         log.debug('Running command on remote host: %s', cmd)
 
-        stdin, stdout, stderr = self.ssh.exec_command(cmd)
+        stdin, stdout, stderr = self.ssh.exec_command(cmd, timeout=self.TIMEOUT)
 
         # stdout.channel represents channel for both stdout and stderr
         channel = stdout.channel
+
+        # there seems to be no way to tell whether the remote is alive,
+        # so just use the counter
+        # https://phab.qadevel.cloud.fedoraproject.org/T593
+        alive_counter = 0
         while not channel.exit_status_ready():
             if channel.recv_ready():
                 data = channel.recv(1024)
                 self.outstream.write(data)
+                alive_counter = 0
             if channel.recv_stderr_ready():
                 data = channel.recv_stderr(1024)
                 self.outstream.write(data)
+                alive_counter = 0
+
             sleep(0.1)
+            alive_counter += 0.1
+
+            if alive_counter >= self.TIMEOUT:
+                raise exc.TaskotronRemoteError('Has not received any output from the remote '
+                                               '%s@%s:%s for %d seconds',
+                                               (self.username, self.hostname, self.port,
+                                                self.TIMEOUT))
 
         retcode = channel.recv_exit_status()
 
@@ -187,7 +206,7 @@
         try:
             with self.sftp.open(remote_path, 'w') as remote_file:
                 remote_file.write(data)
-        except IOError, e:
+        except (socket.error, IOError), e:
             raise exc.TaskotronRemoteError('Could not write data to %s@%s:%s: %s' %
                                            (self.username, self.hostname, remote_path, e.strerror))
 
@@ -211,7 +230,7 @@
         log.debug('Putting file (%s) on to remote host (%s)', local_path, remote_path)
         try:
             return self.sftp.put(local_path, remote_path)
-        except IOError, e:
+        except (socket.error, IOError), e:
             raise exc.TaskotronRemoteError('Could not put file %s to %s@%s:%s: %s' %
                                            (local_path, self.username, self.hostname,
                                             remote_path, e.strerror))
@@ -228,7 +247,7 @@
         log.debug('Getting file from remote host %s to %s', remote_path, local_path)
         try:
             self.sftp.get(remote_path, local_path)
-        except IOError, e:
+        except (socket.error, IOError), e:
             raise exc.TaskotronRemoteError('Could not copy file %s@%s:%s to %s: %s' %
                                            (self.username, self.hostname, remote_path,
                                             local_path, e.strerror))
diff --git a/testing/test_remote_exec.py b/testing/test_remote_exec.py
--- a/testing/test_remote_exec.py
+++ b/testing/test_remote_exec.py
@@ -36,6 +36,7 @@
     def __init__(self, cmd):
         self.cmd = cmd
         self._status_ready = False
+        self._timeout = None
 
     def exit_status_ready(self):
         ret = self._status_ready
@@ -57,6 +58,9 @@
     def recv_exit_status(self):
         return self.cmd
 
+    def settimeout(self, timeout):
+        self._timeout = timeout
+
 
 class StubSFTPClient(object):
     def __init__(self, *args, **kwargs):
@@ -103,6 +107,9 @@
     def mkdir(self, *args, **kwargs):
         pass
 
+    def get_channel(self):
+        return StubChannel('')
+
 
 class StubSSHClient(object):
     def __init__(self, *args, **kwargs):
@@ -128,7 +135,7 @@
 
         return self._sftp
 
-    def exec_command(self, cmd):
+    def exec_command(self, cmd, timeout=None):
         ch = Munch(channel=StubChannel(cmd), read=lambda: '')
 
         return ch, ch, ch

