Created
July 13, 2016 20:34
-
-
Save Girgitt/2df036f9e26dba1baaddf4c5845a20a2 to your computer and use it in GitHub Desktop.
multithreaded sftp server in python based on https://github.com/rspivak/sftpserver
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import time | |
import socket | |
import optparse | |
import sys | |
import textwrap | |
import paramiko | |
from sftpserver.stub_sftp import StubServer, StubSFTPServer | |
import threading | |
HOST, PORT = 'localhost', 3373 | |
BACKLOG = 10 | |
class ConnHandlerThd(threading.Thread): | |
def __init__(self, conn, keyfile): | |
threading.Thread.__init__(self) | |
self._conn = conn | |
self._keyfile = keyfile | |
def run(self): | |
host_key = paramiko.RSAKey.from_private_key_file(self._keyfile) | |
transport = paramiko.Transport(self._conn) | |
transport.add_server_key(host_key) | |
transport.set_subsystem_handler( | |
'sftp', paramiko.SFTPServer, StubSFTPServer) | |
server = StubServer() | |
transport.start_server(server=server) | |
channel = transport.accept() | |
while transport.is_active(): | |
time.sleep(1) | |
def start_server(host, port, keyfile, level): | |
paramiko_level = getattr(paramiko.common, level) | |
paramiko.common.logging.basicConfig(level=paramiko_level) | |
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) | |
server_socket.bind((host, port)) | |
server_socket.listen(BACKLOG) | |
while True: | |
conn, addr = server_socket.accept() | |
srv_thd = ConnHandlerThd(conn, keyfile) | |
srv_thd.setDaemon(True) | |
srv_thd.start() | |
def main(): | |
usage = """\ | |
usage: sftpserver [options] | |
-k/--keyfile should be specified | |
""" | |
parser = optparse.OptionParser(usage=textwrap.dedent(usage)) | |
parser.add_option( | |
'--host', dest='host', default=HOST, | |
help='listen on HOST [default: %default]') | |
parser.add_option( | |
'-p', '--port', dest='port', type='int', default=PORT, | |
help='listen on PORT [default: %default]' | |
) | |
parser.add_option( | |
'-l', '--level', dest='level', default='INFO', | |
help='Debug level: WARNING, INFO, DEBUG [default: %default]' | |
) | |
parser.add_option( | |
'-k', '--keyfile', dest='keyfile', metavar='FILE', | |
help='Path to private key, for example /tmp/test_rsa.key' | |
) | |
options, args = parser.parse_args() | |
if options.keyfile is None: | |
parser.print_help() | |
sys.exit(-1) | |
start_server(options.host, options.port, options.keyfile, options.level) | |
if __name__ == '__main__': | |
main() |
yes, as you said, it's letting anybody in. Can it be set to authenticate with the key? If you have time, can you do it? Thanks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Before using it please make sure the connection is actually authenticated against the configured key. I have not used this code for a while but remember a case when it was letting everyone in :)
Use at your own risk.