mirror of https://github.com/huashengdun/webssh
add proxy
parent
1cf19c7186
commit
b60acbaf00
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (webssh)" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/webssh.iml" filepath="$PROJECT_DIR$/.idea/webssh.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
9
|
||||
README.md,8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
9
|
||||
README.md,8/e/8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="SonarLintModuleSettings">
|
||||
<option name="uniqueId" value="3fc80e5d-f723-4353-8cca-79f0f3561461" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,113 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="4c3fa67e-67e3-4d45-a581-de095d94f3ad" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/webssh/handler.py" beforeDir="false" afterPath="$PROJECT_DIR$/webssh/handler.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/webssh/static/js/main.js" beforeDir="false" afterPath="$PROJECT_DIR$/webssh/static/js/main.js" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"associatedIndex": 7
|
||||
}</component>
|
||||
<component name="ProjectId" id="2W7ocgeQUfLJH8PAp9M4UcIppVE" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="showLibraryContents" value="true" />
|
||||
<option name="showModules" value="false" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"WebServerToolWindowFactoryState": "false",
|
||||
"git-widget-placeholder": "master",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager" selected="Python.main">
|
||||
<configuration name="main" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="webssh" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/webssh" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/webssh/main.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="run" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
||||
<module name="webssh" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="SDK_NAME" value="Python 3.9 (webssh)" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="false" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/run.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="Python.main" />
|
||||
<item itemvalue="Python.run" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="4c3fa67e-67e3-4d45-a581-de095d94f3ad" name="Changes" comment="" />
|
||||
<created>1696093060393</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1696093060393</updated>
|
||||
<workItem from="1696093062322" duration="3000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||
<SUITE FILE_PATH="coverage/webssh$main.coverage" NAME="main Coverage Results" MODIFIED="1696500269853" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/webssh" />
|
||||
<SUITE FILE_PATH="coverage/webssh$run.coverage" NAME="run Coverage Results" MODIFIED="1696093175682" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||
</component>
|
||||
</project>
|
|
@ -6,6 +6,7 @@ import struct
|
|||
import traceback
|
||||
import weakref
|
||||
import paramiko
|
||||
import socks
|
||||
import tornado.web
|
||||
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
@ -29,7 +30,6 @@ try:
|
|||
except ImportError:
|
||||
from urlparse import urlparse
|
||||
|
||||
|
||||
DEFAULT_PORT = 22
|
||||
|
||||
swallow_http_errors = True
|
||||
|
@ -101,7 +101,6 @@ class SSHClient(paramiko.SSHClient):
|
|||
|
||||
|
||||
class PrivateKey(object):
|
||||
|
||||
max_length = 16384 # rough number
|
||||
|
||||
tag_to_name = {
|
||||
|
@ -143,7 +142,7 @@ class PrivateKey(object):
|
|||
logging.debug('Reset offset to {}.'.format(offset))
|
||||
|
||||
logging.debug('Try parsing it as {} type key'.format(name))
|
||||
pkeycls = getattr(paramiko, name+'Key')
|
||||
pkeycls = getattr(paramiko, name + 'Key')
|
||||
pkey = None
|
||||
|
||||
try:
|
||||
|
@ -179,12 +178,11 @@ class PrivateKey(object):
|
|||
msg = 'Invalid key'
|
||||
if self.password:
|
||||
msg += ' or wrong passphrase "{}" for decrypting it.'.format(
|
||||
self.password)
|
||||
self.password)
|
||||
raise InvalidValueError(msg)
|
||||
|
||||
|
||||
class MixinHandler(object):
|
||||
|
||||
custom_headers = {
|
||||
'Server': 'TornadoServer'
|
||||
}
|
||||
|
@ -313,8 +311,7 @@ class NotFoundHandler(MixinHandler, tornado.web.ErrorHandler):
|
|||
|
||||
|
||||
class IndexHandler(MixinHandler, tornado.web.RequestHandler):
|
||||
|
||||
executor = ThreadPoolExecutor(max_workers=cpu_count()*5)
|
||||
executor = ThreadPoolExecutor(max_workers=cpu_count() * 5)
|
||||
|
||||
def initialize(self, loop, policy, host_keys_settings):
|
||||
super(IndexHandler, self).initialize(loop)
|
||||
|
@ -383,9 +380,9 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
|
|||
if self.ssh_client._system_host_keys.lookup(key) is None:
|
||||
if self.ssh_client._host_keys.lookup(key) is None:
|
||||
raise tornado.web.HTTPError(
|
||||
403, 'Connection to {}:{} is not allowed.'.format(
|
||||
hostname, port)
|
||||
)
|
||||
403, 'Connection to {}:{} is not allowed.'.format(
|
||||
hostname, port)
|
||||
)
|
||||
|
||||
def get_args(self):
|
||||
hostname = self.get_hostname()
|
||||
|
@ -396,6 +393,19 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
|
|||
passphrase = self.get_argument('passphrase', u'')
|
||||
totp = self.get_argument('totp', u'')
|
||||
|
||||
# proxyType, proxyIp, proxyPort, proxyRdns = true, proxyUser, proxyPass
|
||||
|
||||
proxyType = self.get_argument('proxytype', None)
|
||||
if proxyType is not None and proxyType != '':
|
||||
proxyType = int(proxyType)
|
||||
proxyIp = self.get_argument('proxyip', u'')
|
||||
proxyPort = self.get_argument('proxyport', None)
|
||||
if proxyPort is not None and proxyPort != '':
|
||||
proxyPort = int(proxyPort)
|
||||
proxyRdns = self.get_argument('proxyrdns', u'')
|
||||
proxyUser = self.get_argument('proxyuser', u'')
|
||||
proxyPass = self.get_argument('proxypass', u'')
|
||||
|
||||
if isinstance(self.policy, paramiko.RejectPolicy):
|
||||
self.lookup_hostname(hostname, port)
|
||||
|
||||
|
@ -405,7 +415,8 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
|
|||
pkey = None
|
||||
|
||||
self.ssh_client.totp = totp
|
||||
args = (hostname, port, username, password, pkey)
|
||||
args = (
|
||||
hostname, port, username, password, pkey, proxyType, proxyIp, proxyPort, proxyRdns, proxyUser, proxyPass)
|
||||
logging.debug(args)
|
||||
|
||||
return args
|
||||
|
@ -446,13 +457,33 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
|
|||
logging.warning('Could not detect the default encoding.')
|
||||
return 'utf-8'
|
||||
|
||||
def http_proxy_tunnel_connect(self, proxy, target, timeout=None):
|
||||
logging.info('Connecting to proxy {}'.format(proxy))
|
||||
logging.info('Connecting to target {}'.format(target))
|
||||
sock = socks.socksocket()
|
||||
sock.set_proxy(*proxy)
|
||||
sock.connect(target)
|
||||
sock.settimeout(timeout)
|
||||
return sock
|
||||
|
||||
def ssh_connect(self, args):
|
||||
ssh = self.ssh_client
|
||||
dst_addr = args[:2]
|
||||
logging.info(args)
|
||||
logging.info('Connecting to {}:{}'.format(*dst_addr))
|
||||
|
||||
sock = None
|
||||
if len(args) > 5:
|
||||
if args[6] is not None and args[6] != '':
|
||||
# 从args中获取代理信息
|
||||
sock = self.http_proxy_tunnel_connect(
|
||||
proxy=args[5:],
|
||||
target=dst_addr,
|
||||
timeout=5000
|
||||
)
|
||||
|
||||
try:
|
||||
ssh.connect(*args, timeout=options.timeout)
|
||||
ssh.connect(*args[:5], timeout=options.timeout, sock=sock)
|
||||
except socket.error:
|
||||
raise ValueError('Unable to connect to {}:{}'.format(*dst_addr))
|
||||
except paramiko.BadAuthenticationType:
|
||||
|
@ -503,6 +534,7 @@ class IndexHandler(MixinHandler, tornado.web.RequestHandler):
|
|||
|
||||
self.check_origin()
|
||||
|
||||
logging.info('Connected from {}'.format(self.get_args()))
|
||||
try:
|
||||
args = self.get_args()
|
||||
except InvalidValueError as exc:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue