Score:0

HaProxy accept-proxy + send-proxy เชื่อมต่อจริงๆ

ธง br

การใช้งานปัจจุบันของฉันมีดังนี้:

  1. ด้านหน้า AWS Load Balancer (ประเภทเครือข่าย TCP/UDP) บนสแต็กคู่ ซึ่งเปลี่ยนเส้นทางไปยังฟลีตของอินสแตนซ์ EC2
  2. อินสแตนซ์ EC2 เหล่านี้กำลังเรียกใช้ HaProxy เพื่อรับคำขอไปยังรายการกระบวนการ
  3. รายการกระบวนการคืออินสแตนซ์ aiosmtpd (จาก Python)

เนื่องจากจุดประสงค์คือการเชื่อมต่อผ่าน SMTP ฉันจำเป็นต้องทราบ IP ของไคลเอ็นต์ แต่ฉันต้องส่งการตอบกลับก่อนด้วย

ที่ผมสังเกตคือถ้า

  • ฉันผูกส่วนหน้าโดยไม่ต้อง ผู้รับมอบฉันทะ
  • แต่เปลี่ยนเส้นทางเซิร์ฟเวอร์ที่สำรองไว้โดยการส่ง ส่งพร็อกซี
  • และปิดใช้งาน Proxy v2 บน AWS Load Balancer

มันทำงานได้อย่างสมบูรณ์ ... สำหรับ IPv4 เท่านั้น (?) !

IPv6 ใช้งานไม่ได้ และพร็อกซีส่งคืน IP ของ AWS Load Balancer ให้ฉันแทน

ดังนั้นฉันจึงลองเปิดใช้งาน Proxy v2 ที่ระดับ AWS การตั้งค่า ผู้รับมอบฉันทะ ที่ส่วนหน้า ผูก และ ส่งพร็อกซี บน เซิร์ฟเวอร์ คุณสมบัติแบ็กเอนด์

คราวนี้ใช้ได้กับทั้ง IPv4/v6 แต่จะไม่ส่งการตอบกลับเริ่มต้น: จะไม่มีการเชื่อมต่อกับโค้ดไพธอนจนกว่าจะส่งบรรทัดแรกจากไคลเอ็นต์!

สิ่งนี้เป็นไปไม่ได้ในโปรโตคอล SMTP: ในฐานะเซิร์ฟเวอร์ ฉันต้องเป็นคนแรกที่ส่งการตอบกลับ

เกิดอะไรขึ้น?

นี่คือการกำหนดค่า HaProxy ของฉัน:

ทั่วโลก
    บันทึก /dev/log local0.log
    บันทึก /dev/log local1 ประกาศ
    chroot /var/lib/haproxy
    ผู้ใช้แฮพร็อกซี
    กลุ่ม haproxy
    ภูต

    แม็กซ์คอน60000

    # การเข้ารหัสเริ่มต้นเพื่อใช้กับซ็อกเก็ตการฟังที่เปิดใช้งาน SSL
    # สำหรับข้อมูลเพิ่มเติม โปรดดูที่ ciphers(1SSL) รายการนี้มาจาก:
    # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
    # สามารถรับรายการทางเลือกพร้อมคำสั่งเพิ่มเติมได้จาก
    # 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-options ต้องการรหัสลูกค้า 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-tickets


ค่าเริ่มต้น
    หมดเวลาเชื่อมต่อ 5 วินาที
    ไคลเอ็นต์หมดเวลา 30 วินาที
    เซิร์ฟเวอร์หมดเวลา 30 วินาที
    โหมด tcp


smtp ส่วนหน้า
    ผูก: 25 ยอมรับพร็อกซี
    ผูก :::25 ยอมรับพร็อกซี

    default_backend smtp_backend


แบ็กเอนด์ smtp_backend
    โหมด tcp
    หมดเวลาเซิร์ฟเวอร์ 1 ม
    หมดเวลาเชื่อมต่อ 5 วินาที

    เซิร์ฟเวอร์ srv1 127.0.0.1:2525 send-proxy maxconn 500

ฉันพยายามเพิ่ม/ลบอย่างใดอย่างหนึ่งหรือทั้งสองอย่างหรือไม่มีเลย ผู้รับมอบฉันทะ และ ส่งพร็อกซี และแม้กระทั่ง send-proxy-v2. ไร้โชค!

สิ่งที่ใกล้เคียงที่สุดที่ฉันเคยใช้งานมาคือไม่มีการเปิดใช้งาน Proxy v2 ที่ส่วนท้ายของ AWS ไม่ใช่ ผู้รับมอบฉันทะ ในส่วนหน้าและ ส่งพร็อกซี บนไคลเอนต์ แต่ใช้ไม่ได้กับ IPv6


ฉันได้สร้างสคริปต์พื้นฐานเพื่ออธิบายปัญหา:

# -*- การกำหนดค่า:utf-8 -*-
นำเข้าซ็อกเก็ต argparse


คลาส TestingServer (วัตถุ):
    def __init__(ตัวเอง โฮสต์ พอร์ต):
        self.sock = socket.socket(ซ็อกเก็ต.AF_INET6)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, จริง)
        self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, เท็จ)
        self.sock.bind((โฮสต์, พอร์ต))
        พิมพ์ ('การตั้งค่าผู้ฟังใน {}:{}'.format (โฮสต์, พอร์ต))

    def ฟัง (ตัวเอง):
        พิมพ์('กำลังรอการเชื่อมต่อ ...')
        self.sock.listen()

        ในขณะที่ทรู:
            พยายาม:
                ลูกค้า ที่อยู่ = self.sock.accept()
                พิมพ์('มีการเชื่อมต่อ!' ที่อยู่)
                client.send(b'250 กำลังส่งข้อมูลเริ่มต้น\r\n')
                ข้อมูล = client.recv(1024)
                พิมพ์ ('ข้อมูลที่ได้รับ:' ข้อมูล)
                client.send(b'250 Gotcha')
                ข้อมูล = client.recv(1024)
                พิมพ์('ได้รับข้อมูล 2:', ข้อมูล)
                client.send (b'250 วินาที gotcha')
                ลูกค้า.ปิด()
            ยกเว้น ข้อยกเว้นเป็น e:
                พิมพ์ ('มีข้อยกเว้น!', จ)
                ผ่าน
            ในที่สุด:
                พยายาม:
                    ลูกค้า.ปิด()
                ยกเว้น ข้อยกเว้น:
                    ผ่าน


ถ้า __name__ == '__main__':
    parser = argparse.ArgumentParser(description='เริ่ม SMTPD daemon')
    parser.add_argument('--host', nargs='?', default='localhost', type=str)
    parser.add_argument('--port', nargs='?', default=2552, type=int)
    หาเรื่อง = parser.parse_args()

    TestingServer(args.host, args.port).listen()

เมื่อตั้งค่าเปิดใช้งาน AWS Proxy v2 ด้วย ผู้รับมอบฉันทะ สำหรับ ผูก และ ส่งพร็อกซี สำหรับ เซิร์ฟเวอร์นี่คือสิ่งที่เกิดขึ้น:

ฉันเริ่มเซิร์ฟเวอร์:

$> หลาม testserver.py --port 2525 --host ::

ตั้งค่าการฟังบน :::2525

กำลังรอการเชื่อมต่อ ...

บนเครื่องของฉัน ฉันทำ:

$> เทลเน็ต {aws-loadbalancer-name}.elb.eu-west-3.amazonaws.com 25

กำลังพยายาม {ipv6}...

เชื่อมต่อกับ {aws-loadbalancer-name}.elb.eu-west-3.amazonaws.com

อักขระ Escape คือ '^]'

ยังไม่มีอะไรบนเซิร์ฟเวอร์

ในตอนท้ายของลูกค้า (telnet) ฉันเขียนอะไรก็ได้:

$> ก [ป้อน]

จากนั้น ทันทีที่ฉันกด Enter เซิร์ฟเวอร์จะแสดงสิ่งต่อไปนี้:

ที่อยู่คือ: ('::ffff:127.0.0.1', 42494, 0, 0)

มีการเชื่อมต่อ! <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)

ข้อมูลที่ได้รับ: b'PROXY TCP6 {clients_ip} {loadbalancer_ip} 44012 25\r\ns\r\n'

เห็นได้ชัดว่าด้วยเหตุผลบางอย่าง HaProxy ไม่ส่งการเชื่อมต่อไปยังกระบวนการ Python ทันทีที่ถูกสร้างขึ้น แต่จะรอให้ข้อมูลแรกมาถึง

ฉันจะหลีกเลี่ยงสิ่งนั้นได้อย่างไร

ขอบคุณล่วงหน้า!

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา