thực hiện hiện tại của tôi là như sau:
- Ở phía trước, một AWS Load Balancer (loại Network TCP/UDP) trên ngăn xếp kép, chuyển hướng đến một nhóm các phiên bản EC2
- Các phiên bản EC2 này đang chạy HaProxy để nhận các yêu cầu đối với danh sách các quy trình
- Danh sách các quy trình là các phiên bản aiosmtpd (từ Python).
Vì mục đích là kết nối qua SMTP, tôi cần biết IP của Máy khách, nhưng tôi cũng cần gửi phản hồi trước.
Những gì tôi nhận thấy là nếu
- Tôi ràng buộc giao diện người dùng mà không cần
chấp nhận-proxy
- nhưng chuyển hướng máy chủ được hỗ trợ bằng cách gửi
gửi-proxy
- Và tắt Proxy v2 trên AWS Load Balancer
nó hoạt động hoàn hảo ... chỉ dành cho IPv4 (??)!
IPv6 không hoạt động và thay vào đó, Proxy trả lại cho tôi IP của Bộ cân bằng tải AWS.
Vì vậy, tôi đã thử bật Proxy v2 ở cấp AWS, cài đặt chấp nhận-proxy
trên giao diện người dùng trói buộc
và gửi-proxy
trên người phục vụ
tài sản phụ trợ.
Lần này, nó hoạt động cho cả IPv4/v6, NHƯNG, nó không bao giờ gửi phản hồi ban đầu: Không có kết nối nào được thực hiện với mã python cho đến khi dòng đầu tiên được gửi từ máy khách!
Trong giao thức SMTP, điều này là không thể: Với tư cách là máy chủ, tôi phải là người đầu tiên gửi phản hồi.
Điều gì đang xảy ra?
Đây là cấu hình HaProxy của tôi:
toàn cầu
nhật ký/dev/log cục bộ0
log /dev/log local1 thông báo
chroot /var/lib/haproxy
người dùng haproxy
nhóm haproxy
yêu tinh
maxconn 60000
# Mật mã mặc định để sử dụng trên ổ cắm nghe hỗ trợ SSL.
# Để biết thêm thông tin, hãy xem mật mã (1SSL). Danh sách này là từ:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# Có thể lấy danh sách thay thế với các chỉ thị bổ sung từ
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA -CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-optionsprefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA -CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-ticket
mặc định
hết thời gian kết nối 5s
máy khách hết thời gian 30 giây
máy chủ hết thời gian 30s
chế độ tcp
giao diện người dùng smtp
liên kết :25 chấp nhận proxy
liên kết :::25 chấp nhận-proxy
default_backend smtp_backend
phụ trợ smtp_backend
chế độ tcp
máy chủ hết thời gian chờ 1 phút
hết thời gian kết nối 5s
máy chủ srv1 127.0.0.1:2525 gửi proxy maxconn 500
Tôi đã thử thêm/xóa một trong hai hoặc cả hai hoặc không cái nào chấp nhận-proxy
và gửi-proxy
và ngay cả gửi-proxy-v2
. Không có bất kỳ may mắn!
Lần gần nhất tôi thấy nó hoạt động là không có Proxy v2 nào được bật ở cuối AWS, không chấp nhận-proxy
trên phần frontend và gửi-proxy
trên máy khách, nhưng nó không hoạt động với IPv6.
Tôi đã tạo một tập lệnh cơ bản để mô tả sự cố:
# -*- cấu hình:utf-8 -*-
ổ cắm nhập khẩu, argparse
lớp Máy chủ kiểm tra (đối tượng):
def __init__(bản thân, máy chủ, cổng):
self.sock = socket.socket(socket.AF_INET6)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, False)
self.sock.bind((máy chủ, cổng))
print('Đang thiết lập trình nghe trên {}:{}'.format(host, port))
chắc chắn lắng nghe (bản thân):
print('Đang chờ kết nối...')
self.sock.listen()
trong khi Đúng:
cố gắng:
khách hàng, địa chỉ = self.sock.accept()
print('Có kết nối!', địa chỉ)
client.send(b'250 Đang gửi dữ liệu ban đầu.\r\n')
dữ liệu = client.recv(1024)
print('Dữ liệu nhận được:', dữ liệu)
client.send(b'250 Gotcha')
dữ liệu = client.recv(1024)
print('Dữ liệu nhận được 2:', dữ liệu)
client.send(b'250 Gotcha thứ hai')
khách hàng.đóng()
ngoại trừ Ngoại lệ như e:
print('Có một ngoại lệ!', e)
vượt qua
cuối cùng:
cố gắng:
khách hàng.đóng()
ngoại trừ Ngoại lệ:
vượt qua
nếu __name__ == '__main__':
trình phân tích cú pháp = argparse.ArgumentParser(description='Bắt đầu trình nền SMTPD.')
parser.add_argument('--host', nargs='?', default='localhost', type=str)
parser.add_argument('--port', nargs='?', default=2552, type=int)
args = trình phân tích cú pháp.parse_args()
Máy chủ kiểm tra (args.host, args.port).listen()
Khi bật AWS Proxy v2, với chấp nhận-proxy
vì trói buộc
và gửi-proxy
vì người phục vụ
, đây là những gì đang xảy ra:
Tôi khởi động máy chủ:
$> python testserver.py --port 2525 --host ::
Thiết lập trình nghe trên :::2525
Đang chờ kết nối...
Trên máy cục bộ của tôi, tôi thực hiện:
$> telnet {aws-loadbalancer-name}.elb.eu-west-3.amazonaws.com 25
Đang thử {ipv6}...
Đã kết nối với {aws-loadbalancer-name}.elb.eu-west-3.amazonaws.com.
Ký tự thoát là '^]'.
Chưa có gì trên máy chủ.
Ở phía khách hàng (telnet), tôi viết bất cứ thứ gì:
$> một [nhập]
Sau đó, ngay khi tôi nhấn enter, máy chủ sẽ hiển thị như sau:
Địa chỉ là: ('::ffff:127.0.0.1', 42494, 0, 0)
Có một kết nối! <socket.socket fd=4, family=AddressFamily.AF_INET6, type=SocketKind.SOCK_STREAM, proto=0, laddr=('::ffff:127.0.0.1', 2525, 0, 0), raddr=(':: ffff:127.0.0.1', 42494, 0, 0)> ('::ffff:127.0.0.1', 42494, 0, 0)
Dữ liệu đã nhận: b'PROXY TCP6 {clients_ip} {loadbalancer_ip} 44012 25\r\ns\r\n'
Vì vậy, rõ ràng là vì một lý do nào đó, HaProxy không gửi kết nối đến quy trình Python ngay khi một kết nối được tạo mà chờ dữ liệu đầu tiên đến.
Làm thế nào tôi có thể tránh điều đó?
Cảm ơn bạn trước!