-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Secure FTP #37
Comments
yes, it's just tunneling... i was thinking of FTPS - actually this might be quite simple, but as usually the main problem is finding free time for doing things (especially with a full-time job) |
👍 Any updates on this? Happy to help out. |
@creatorrr, I tried out ssl module: import asyncio
import ssl
req = b"GET / HTTP/1.1\r\nHost: www.python.org\r\n\r\n"
async def flush(outgoing, writer):
if outgoing.pending:
writer.write(outgoing.read())
await writer.drain()
async def foo():
BLOCK_SIZE = 8192
# ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ssl_context = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
ssl_context.check_hostname = False
incoming = ssl.MemoryBIO()
outgoing = ssl.MemoryBIO()
ssl_object = ssl_context.wrap_bio(incoming, outgoing)
reader, writer = await asyncio.open_connection("python.org", 443)
while True:
try:
ssl_object.do_handshake()
break
except ssl.SSLWantReadError:
await flush(outgoing, writer)
incoming.write(await reader.read(BLOCK_SIZE))
ssl_object.write(req)
await flush(outgoing, writer)
data = None
while True:
try:
data = ssl_object.read(BLOCK_SIZE)
print(data)
except ssl.SSLWantReadError:
await flush(outgoing, writer)
await flush(outgoing, writer)
data = await reader.read(BLOCK_SIZE)
# print("->", data)
if not data:
break
incoming.write(data)
writer.close()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(foo()) But it's pretty annoying… also, I was thinking about who will need this, since I did not find any FTPS server online. Feel free to implement this functionality is you have enough courage and time 😉 |
Haha, thanks for looking into this, @pohmelie! I will try and see if I can get things to work and create a patch. |
Unfortunately, there is an asyncio bug, which will come out when your path io is slower than network io. Solution for this (except wait for fix) is own wrapper, like present above. |
@pohmelie, for the example code you provided above, I import uvloop and the example code can run without any errors, seems uvloop can fix this issue? |
@markshhsu, it looks like yes. |
Just to note that I'm failing to connect to an SFTP server. Trying to form a connection like this: async with aioftp.Client.context(
host=settings.host,
port=settings.port,
user=settings.username,
password=settings.password.get_secret_value(),
ssl=True,
socket_timeout=10,
path_timeout=10,
) as client:
logger.info("Connected.")
logger.info(str(await client.list())) which results in this error:
If I set the
but nothing happens and I have to interrupt. I can connect to the server with the same information when using cnx_opts = pysftp.CnOpts()
cnx_opts.hostkeys = None
with pysftp.Connection(
host=settings.host,
port=settings.port,
username=settings.username,
password=settings.password.get_secret_value(),
cnopts=cnx_opts,
) as sftp:
logger.info("Connected.")
logger.info(sftp.pwd)
logger.info(sftp.listdir()) Do you have any advice on what I'm doing wrong? |
@Midnighter, since you have success with |
🤔 indeed the distinction between SFTP and FTP over SSH (which you demonstrated in your comment) was not clear to me. Thank you for the heads up. |
FWIW, tried with ssl.create_default_context(), server seems to start, client can't connect... |
@maulberto3 need more context. |
Started working on a raw test implementation for FTPES, but unfortunately didn't get it working. Here is my attempt in case anybody wants to look into it and may have a suggestion or even solution. |
@pantierra
I think that is the problem |
Good point! It looks like we would need for Python v3.11 for this, which includes this PR that makes things much easier: python/cpython#91453. |
Any updates on explicit ftps mode? |
@antonio-hickey |
@pohmelie |
@antonio-hickey |
Hi. I added a quick implementation of explicit TLS (requires Python >= 3.11): 86a6a8c. Pass in For backwards compatibility, passing Use default SSL context:
Use custom SSL context to bypass self-signed cert errors:
I haven't done much testing other than getting this to work within my own project, and I'm not sure how you'd like to handle the tests for it since you've disabled SSL tests, but I figure I'd start the discussion. |
@sammichaels, sounds great! I think it is time to jump onto 3.11 and use recent fixes for ssl and your code to allow explicit switch. I will try to migrate project to modern technologies before this ( |
@pohmelie I'll continue updating the fork with my changes as there's much more to do, like error handling and SSL session reuse. Glad to hear you're considering adding explicit support! |
@sammichaels I moved codebase to |
Hey @sammichaels Need help with the fork? I woul be willing to help so we can make a PR |
@elpablete Hi! I guess I've forgotten to actually submit the PR. I've been running TLS for some time now in production. Let me make sure I have the production code committed to the fork and I'll do a PR. |
After #36 I read about FTPS, SFTP and FTP over SSH.
SFTP is SSH extension and we should ignore it
FTPS is extension of FTP (https://tools.ietf.org/html/rfc2228)
FTP over SSH is (as I realized) just tunneling and have problems(?) with data connections
implicit ftps mode (Add implicit FTPS support #81)
explicit ftps mode
The text was updated successfully, but these errors were encountered: