Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions webssh/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,12 @@ def get_port(self):
raise InvalidValueError('Invalid port: {}'.format(value))
return port

def get_source_address(self):
value = self.get_argument('source_address', u'')
if value and not is_valid_ip_address(value):
raise InvalidValueError('Invalid source ip address: {}'.format(value))
return value

def lookup_hostname(self, hostname, port):
key = hostname if port == 22 else '[{}]:{}'.format(hostname, port)

Expand All @@ -395,6 +401,7 @@ def get_args(self):
privatekey, filename = self.get_privatekey()
passphrase = self.get_argument('passphrase', u'')
totp = self.get_argument('totp', u'')
source_address = self.get_argument('source_address', u'')

if isinstance(self.policy, paramiko.RejectPolicy):
self.lookup_hostname(hostname, port)
Expand All @@ -405,7 +412,7 @@ def get_args(self):
pkey = None

self.ssh_client.totp = totp
args = (hostname, port, username, password, pkey)
args = (hostname, port, username, password, pkey, source_address)
logging.debug(args)

return args
Expand Down Expand Up @@ -451,8 +458,23 @@ def ssh_connect(self, args):
dst_addr = args[:2]
logging.info('Connecting to {}:{}'.format(*dst_addr))

sock = None
source_address = args[5]
if source_address:
logging.info('Connecting source address socket')
sock = socket.socket()
sock.settimeout(options.timeout) # Set a timeout on blocking socket operations
try:
sock.bind((source_address, 0))
except OSError:
raise InvalidValueError('Unable to bind source address {} socket'.format(source_address))
try:
sock.connect(dst_addr)
except socket.error:
raise ValueError('Unable to connect source address socket to {}:{}'.format(*dst_addr))

try:
ssh.connect(*args, timeout=options.timeout)
ssh.connect(*args, sock=sock, timeout=options.timeout)
except socket.error:
raise ValueError('Unable to connect to {}:{}'.format(*dst_addr))
except paramiko.BadAuthenticationType:
Expand Down
2 changes: 2 additions & 0 deletions webssh/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
<input class="form-control" type="password" id="totp" name="totp" value="">
</div>
<div class="col">
<label for="source_address">Source Address (optional)</label>
<input class="form-control" type="text" id="source_address" name="source_address" value="">
</div>
</div>
<input type="hidden" id="term" name="term" value="xterm-256color">
Expand Down