У меня есть код на Python, который принимает (E) SMTP-запросы через aiosmtp, но так как я поместил этот код в Debian 10, у меня есть несколько ошибок, которых раньше не было (и мой код не изменился):
[SSL: NO_SHARED_CIPHER] нет общего шифра (_ssl.c: 1056)
Протокол сбоя при рукопожатии SSL: транспорт: <_SelectorSocketTransport fd = 11 чтение= запись с опросом =>
SSLError: [SSL: NO_SHARED_CIPHER] no shared cipher (_ssl.c:1056)
File "asyncio/sslproto.py", line 625, in _on_handshake_complete
raise handshake_exc
File "asyncio/sslproto.py", line 189, in feed_ssldata
self._sslobj.do_handshake()
File "ssl.py", line 763, in do_handshake
self._sslobj.do_handshake()
и:
[SSL: KRB5_S_INIT] данные приложения после уведомления о закрытии (_ssl.c: 2609)
Ошибка SSL в протоколе получения данных: транспорт: <_SelectorSocketTransport fd = 15 чтение = опрос записи =>
SSLError: [SSL: KRB5_S_INIT] application data after close notify (_ssl.c:2609)
File "asyncio/sslproto.py", line 526, in data_received
ssldata, appdata = self._sslpipe.feed_ssldata(data)
File "asyncio/sslproto.py", line 207, in feed_ssldata
self._sslobj.unwrap()
File "ssl.py", line 767, in unwrap
return self._sslobj.shutdown()
Я думаю, что эти две проблемы связаны.
К сожалению, эти две трассировки стека не показывают ничего, связанного с моим кодом, что затрудняет мне лучшее понимание того, где это происходит, и исключение не связано с другим исключением (Python3).
Вот версии моего пакета:
uname -a: Linux my-server 4.19.0-5-amd64 #1 SMP Debian 4.19.37-5+deb10u2 (2019-08-08) x86_64 GNU/Linux
python - версия: Python 3.7.3
pip freeze
aiomysql==0.0.20
aiosmtpd==1.2
asn1crypto==0.24.0
atpublic==1.0
authres==1.2.0
beanstalkc3==0.4.0
blinker==1.4
certifi==2018.8.24
cffi==1.12.3
chardet==3.0.4
Click==7.0
cloud-init==18.3
configobj==5.0.6
cryptography==2.6.1
distro-info==0.21
dkimpy==0.9.4
dnspython==1.16.0
fail2ban==0.10.2
Flask==1.1.1
idna==2.6
itsdangerous==1.1.0
Jinja2==2.10.1
jsonpatch==1.21
jsonpointer==1.10
jsonschema==2.6.0
MarkupSafe==1.1.0
mysqlclient==1.4.4
oauthlib==2.1.0
psutil==5.6.3
py3dns==3.2.1
pycparser==2.19
PyGObject==3.30.4
pyinotify==0.9.6
PyJWT==1.7.0
PyMySQL==0.9.2
PyNaCl==1.3.0
pyspf==2.0.13
pysrs==1.0.3
python-apt==1.8.4
python-dotenv==0.10.3
PyYAML==3.13
requests==2.21.0
sentry-sdk==0.12.3
six==1.12.0
systemd-python==234
unattended-upgrades==0.1
urllib3==1.24.1
uWSGI==2.0.18
Werkzeug==0.16.0
Я считаю, что если что-то не так с моим кодом,У меня была бы эта ошибка в Debian 9 и более ранних версиях, которой у меня никогда не было.
Я искал в SO и Google эту ошибку, но ничего не нашел. Я подозреваю некоторые проблемы в конкретной версии конкретного проекта (aiosmtpd, async или python), но не имею никакой подсказки.
Я надеюсь, что вы сможете мне помочь:)
Обновление:
Я добавил отслеживание шифров в сообщении. Общие шифры:
[[TLS_AES_256_GCM_SHA384, TLSv1.3, 256], [TLS_CHACHA20_POLY1305_SHA256, TLSv1.3, 256], [TLS_AES_128_GCM_SHA256, TLSv1.3, 128], [ECDHE-ECDSA-AES256-GCM-SHA384, TLSv1.2, 256], [ECDHE-RSA-AES256-GCM-SHA384, TLSv1.2, 256], [DHE-RSA-AES256-GCM-SHA384, TLSv1.2, 256], [ECDHE-ECDSA-CHACHA20-POLY1305, TLSv1.2, 256], [ECDHE-RSA-CHACHA20-POLY1305, TLSv1.2, 256], [DHE-RSA-CHACHA20-POLY1305, TLSv1.2, 256], [ECDHE-ECDSA-AES128-GCM-SHA256, TLSv1.2, 128], [ECDHE-RSA-AES128-GCM-SHA256, TLSv1.2, 128]]
И шифр для сокета: [ECDHE-RSA-AES256-GCM-SHA384, TLSv1.2, 256]
, который находится в общих шифрах.
Обновление 2
Iможет воспроизвести ошибку, но только при определенных условиях.
На новом сервере, вот код, который я запускаю:
import asyncio, logging, sys, signal, ssl
from aiosmtpd.controller import Controller
from aiosmtpd.handlers import Debugging
from aiosmtpd.smtp import SMTP
class ControllerTls(Controller):
def factory(self):
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('./certs/certificate.pem', './certs/id_rsa')
context.load_dh_params('./certs/dhparams.pem')
return SMTP(
self.handler,
tls_context=context
)
# Temporary outputing errors from mail.log
streamHandler = logging.StreamHandler(sys.stdout)
streamHandler.setFormatter(logging.Formatter('[%(asctime)-15s] (%(levelname)s) - %(message)s'))
streamHandler.setLevel(logging.INFO)
maillog = logging.getLogger('mail.log')
maillog.setLevel(logging.INFO)
maillog.addHandler(streamHandler)
controller = ControllerTls(Debugging(), hostname='0.0.0.0', port=2125)
controller.start()
print('Controller started!')
sig = signal.sigwait([signal.SIGINT, signal.SIGQUIT])
controller.stop()
Это базовый сценарий, который помогает мне воспроизвести проблему.
На старом сервере я запускаю этот код:
import smtplib, ssl, sys
port = 25
if len(sys.argv) == 3:
port = sys.argv[2]
def com(client, command, *args, **kwargs):
result = getattr(client, command)(*args, **kwargs)
if result[0] > 500:
print('[FATAL] - An error occured!')
print(result)
client.quit()
exit()
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('/var/www/towboat/certs/certificate.pem', '/var/www/towboat/certs/id_rsa')
context.set_ciphers('ECDHE-ECDSA-AES256-GCM-SHA384')
client = smtplib.SMTP(sys.argv[1], port=port)
com(client, 'ehlo')
com(client, 'starttls', context=context)
com(client, 'ehlo')
com(client, 'mail', 'contact@improvmx.com')
com(client, 'rcpt', 'cyril@improvmx.com')
com(client, 'quit')
print('All good !')
, которому я звоню:
sendmail.py {ip.of.new.server} 2125
На старом сервере (тот,запускает скрипт), я получаю эту ошибку:
Controller started!
[2019-10-08 15:57:11,878] (INFO) - Peer: ('ip.of.old.server', 45492)
[2019-10-08 15:57:11,878] (INFO) - ('ip.of.old.server', 45492) handling connection
[2019-10-08 15:57:11,880] (INFO) - ('ip.of.old.server', 45492) Data: b'ehlo {name old server}'
[2019-10-08 15:57:11,883] (INFO) - ('ip.of.old.server', 45492) Data: b'STARTTLS'
[2019-10-08 15:57:11,883] (INFO) - ('ip.of.old.server', 45492) STARTTLS
SSL handshake failed
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f04d33d7d30>
transport: <_SelectorSocketTransport fd=7 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
File "/usr/lib/python3.7/asyncio/sslproto.py", line 625, in _on_handshake_complete
raise handshake_exc
File "/usr/lib/python3.7/asyncio/sslproto.py", line 189, in feed_ssldata
self._sslobj.do_handshake()
File "/usr/lib/python3.7/ssl.py", line 763, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: NO_SHARED_CIPHER] no shared cipher (_ssl.c:1056)
SSL error in data received
protocol: <asyncio.sslproto.SSLProtocol object at 0x7f04d33d7d30>
transport: <_SelectorSocketTransport closing fd=7 read=idle write=<idle, bufsize=0>>
Traceback (most recent call last):
File "/usr/lib/python3.7/asyncio/sslproto.py", line 526, in data_received
ssldata, appdata = self._sslpipe.feed_ssldata(data)
File "/usr/lib/python3.7/asyncio/sslproto.py", line 189, in feed_ssldata
self._sslobj.do_handshake()
File "/usr/lib/python3.7/ssl.py", line 763, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: NO_SHARED_CIPHER] no shared cipher (_ssl.c:1056)
[2019-10-08 15:58:33,909] (INFO) - Connection lost during _handle_client()
Что странно, если я скопирую скрипт sendmail на свой локальный компьютер и запустлю его, указывая на новый сервер, у меня не будетошибка больше!
(Значит, проблема должна быть связана со старым сервером? Но почему новый сервер показывает исключение?!)
Если я переключаю сценарии (тестирую отправку электронного письма сновый сервер на старый), работает ...