ฉันมีเซิร์ฟเวอร์ postfix ที่ทำงานได้ดี (ขาเข้าและขาออก) จนกว่าฉันจะทำการเปลี่ยนแปลงเครือข่ายบางอย่าง ฉันเพิ่มอินเทอร์เฟซ (สำหรับที่อยู่ IP สาธารณะที่สอง ผ่านอุโมงค์ข้อมูล VPN ฉันตั้งใจที่จะเรียกใช้เซิร์ฟเวอร์ postfix หลายตัว เพื่อรองรับโดเมนที่แยกจากกันในที่อยู่ IP แยกต่างหาก ใบรับรอง ฯลฯ)

หลังจากการเปลี่ยนแปลง postfix จะได้รับอีเมลขาเข้าที่ดี แต่การรับส่งข้อมูลขาออกกำลังออกจากอินเทอร์เฟซที่ไม่ถูกต้อง ดังนั้นจึงไม่สามารถส่งอีเมลได้ (พอร์ต 25 ถูกบล็อกบนอินเทอร์เฟซนั้น) mail.logแสดง "การเชื่อมต่อถูกปฏิเสธ" หรือ "เครือข่ายที่ไม่สามารถเข้าถึงได้" ไปยัง SMTP ต่างประเทศ เซิร์ฟเวอร์

ตัวอย่างข้อความแสดงข้อผิดพลาดจากmail.log:

Oct 18 17:13:10 vox postfix/smtp[22694]: connect to mx-asp.jvlicenses.com[198.199.107.159]:25: Connection timed out
Oct 18 17:13:10 vox postfix/smtp[22694]: 39DCBA6227: to=<[email protected]>, relay=none, delay=1096, delays=1066/0.02/30/0, dsn=4.4.1, status=deferred (connect to mx-asp.jvlicenses.com[198.199.107.159]:25: Connection timed out)

ฉันใช้พารามิเตอร์smtp_bind_addressmaster.cfเพื่อระบุที่อยู่ต้นทางที่ Postfix ควรใช้ ฉันยังได้ลองใช้inet_addressesในmaster.cfแต่ที่ดูเหมือนจะไม่ทำงานอย่างใดอย่างหนึ่ง การรับส่งข้อมูลจะออกจากเกตเวย์เริ่มต้นเสมอ แทนที่จะเป็นอินเทอร์เฟซที่ต้องการ (เมื่อทั้งหมดนี้ใช้งานได้ ฉันคิดว่าเส้นทางเริ่มต้นน่าจะเป็นเส้นทางที่ต้องการ แต่ฉันจำไม่ได้แน่ชัด)

สิ่งที่ฉันต้องการคือให้ postfix จดหมายส่งกับแหล่ง IP ซึ่งตามกฎเส้นทางของฉันควรออกไปอินเตอร์เฟซ10.8.0.8 tun45อย่างที่ฉันบอกได้ดีที่สุดว่า postfix กำลังส่งด้วย IP 192.168.122.185บนอุปกรณ์enp1s0ซึ่งเป็นเส้นทางเริ่มต้นบนโฮสต์

ผมใช้รุ่น postfix 3.4.14ใน 4.19.118-2 (2020-04-24)Debian

รายละเอียดการกำหนดค่าเพิ่มเติมบางอย่างตามมา พร้อมกับขั้นตอนที่ฉันใช้ในการทดสอบ

Postfix ผูกกับ10.8.0.8ตามที่แสดงโดย netstat:

# netstat -ntlp|grep master
tcp        0      0 10.8.0.8:25             0.0.0.0:*               LISTEN      22293/master        
tcp        0      0 10.8.0.8:587            0.0.0.0:*               LISTEN      22293/master        
tcp        0      0 10.8.0.8:465            0.0.0.0:*               LISTEN      22293/master

ที่อยู่นั้นเป็นอุปกรณ์tun45บนโฮสต์:

# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:4b:2c:5b brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.185/24 brd 192.168.122.255 scope global dynamic noprefixroute enp1s0
       valid_lft 2672sec preferred_lft 2672sec
    inet6 fe80::5054:ff:fe4b:2c5b/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
9: tun45: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.8/24 brd 10.8.0.255 scope global tun45
       valid_lft forever preferred_lft forever
    inet6 fe80::e401:70cf:ba68:88b1/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever
11: tun66: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none 
    inet 10.8.0.7/24 brd 10.8.0.255 scope global tun66
       valid_lft forever preferred_lft forever
    inet6 fe80::41d:c2e1:9428:5630/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

เส้นทางไปยังที่อยู่ภายนอกใด ๆ (ในกรณีนี้คือ MTA สำหรับ jvlicenses.com) จาก IP 10.8.0.8ควรผ่านอุปกรณ์tun45:

# ip route get 198.199.107.159 from 10.8.0.8
198.199.107.159 from 10.8.0.8 dev tun45 table t1 uid 0 
    cache 

ตารางเส้นทางt1มีรายการเดียวเท่านั้น:

# ip route show table t1
default dev tun45 scope link

ฉันสามารถเชื่อมต่อกับเซิร์ฟเวอร์ภายนอกโพสต์ 25 โดยใช้ netcat ด้วยที่อยู่ต้นทางเดียวกัน:

# nc -s 10.8.0.8 198.199.107.159 25
220 mx-asp.jvlicenses.com ESMTP Postfix
QUIT
221 2.0.0 Bye

tcpdump แสดงว่าการเชื่อมต่อ netcat มีที่อยู่ต้นทางที่ถูกต้อง ฯลฯ:

# tcpdump -ni tun45 dst port 25
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun45, link-type RAW (Raw IP), capture size 262144 bytes
16:27:02.522570 IP 10.8.0.8.42427 > 198.199.107.159.25: Flags [S], seq 4118387792, win 64240, options [mss 1460,sackOK,TS val 2496426612 ecr 0,nop,wscale 8], length 0
16:27:02.689912 IP 10.8.0.8.42427 > 198.199.107.159.25: Flags [.], ack 1806817019, win 251, options [nop,nop,TS val 2496426779 ecr 75983973], length 0
16:27:02.857545 IP 10.8.0.8.42427 > 198.199.107.159.25: Flags [.], ack 42, win 251, options [nop,nop,TS val 2496426947 ecr 75984142], length 0
16:27:14.393645 IP 10.8.0.8.42427 > 198.199.107.159.25: Flags [P.], seq 0:5, ack 42, win 251, options [nop,nop,TS val 2496438483 ecr 75984142], length 5: SMTP: QUIT
16:27:14.650912 IP 10.8.0.8.42427 > 198.199.107.159.25: Flags [.], ack 57, win 251, options [nop,nop,TS val 2496438740 ecr 75995841], length 0
16:27:14.651089 IP 10.8.0.8.42427 > 198.199.107.159.25: Flags [F.], seq 5, ack 58, win 251, options [nop,nop,TS val 2496438740 ecr 75995842], length 0

แต่เมื่อฉันส่งอีเมลไปยังเซิร์ฟเวอร์นั้น ไม่มีทราฟฟิกใน tun45 ฉันเห็นว่ามันกำลังออกไปตามเส้นทางเริ่มต้นบนอุปกรณ์enp1s0:

# tcpdump -n dst port 25 -vv
tcpdump: listening on enp1s0, link-type EN10MB (Ethernet), capture size 262144 bytes
16:42:37.321194 IP (tos 0x0, ttl 64, id 1567, offset 0, flags [DF], proto TCP (6), length 60)
    192.168.122.185.34050 > 198.199.107.159.25: Flags [S], cksum 0x6df7 (incorrect -> 0xc5e2), seq 3824536030, win 64240, options [mss 1460,sackOK,TS val 17622374 ecr 0,nop,wscale 8], length 0

การยืนยันว่าอันที่จริงนี่คือเส้นทางเริ่มต้นสำหรับโฮสต์ กล่าวคือ เมื่อ IP ต้นทางไม่เป็น10.8.0.8เช่นนั้น ดังนั้นตารางเส้นทางt1จะถูกทริกเกอร์:

# ip route
default via 192.168.122.1 dev enp1s0 proto dhcp metric 100 
10.8.0.0/24 dev tun45 proto kernel scope link src 10.8.0.8 
10.8.0.0/24 dev tun66 proto kernel scope link src 10.8.0.7
<...elided entries...>

# ip route get 198.199.107.159
198.199.107.159 via 192.168.122.1 dev enp1s0 src 192.168.122.185 uid 0 
    cache 

master.cf กำหนดค่า:

10.8.0.8:smtp      inet  n       -       y       -       -       smtpd -v
  -o smtpd_tls_key_file=/etc/letsencrypt/live/<domain>/privkey.pem
  -o smtpd_tls_cert_file=/etc/letsencrypt/live/<domain>/fullchain.pem
  -o smtp_bind_address=10.8.0.8
  -o myhostname=<host.domain>

10.8.0.8:submission inet n       -       y       -       -       smtpd -v
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_tls_key_file=/etc/letsencrypt/live/<domain>/privkey.pem
  -o smtpd_tls_cert_file=/etc/letsencrypt/live/<domain>/fullchain.pem
  -o smtp_bind_address=10.8.0.8
  -o myhostname=<host.domain>

10.8.0.8:smtps     inet  n       -       y       -       -       smtpd -v
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
  -o smtpd_tls_key_file=/etc/letsencrypt/live/<domain>/privkey.pem
  -o smtpd_tls_cert_file=/etc/letsencrypt/live/<domain>/fullchain.pem
  -o smtp_bind_address=10.8.0.8
  -o myhostname=<host.domain>

และpostconf -nผลลัพธ์:

# postconf -n
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
append_dot_mydomain = no
biff = no
compatibility_level = 2
debug_peer_list = 81.3.6.165, 45.55.104.203, 34.209.113.130
delay_warning_time = 4h
disable_vrfy_command = yes
inet_interfaces = all
inet_protocols = all
invalid_hostname_reject_code = 550
mailbox_size_limit = 0
maximal_backoff_time = 3h
milter_default_action = accept
milter_protocol = 6
minimal_backoff_time = 180s
mydestination = localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
myorigin = /etc/mailname
non_fqdn_reject_code = 550
non_smtpd_milters = $smtpd_milters
policyd-spf_time_limit = 3600s
readme_directory = no
recipient_delimiter = +
relayhost =
smtp_always_send_ehlo = yes
smtp_helo_timeout = 15s
smtp_rcpt_timeout = 15s
smtp_tls_security_level = may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname
smtpd_milters = local:opendkim/opendkim.sock
smtpd_recipient_limit = 40
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_recipient, reject_unknown_recipient_domain, reject_unlisted_recipient, reject_unauth_destination, check_policy_service unix:private/policyd-spf
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_sasl_tls_security_options = noanonymous
smtpd_sasl_type = dovecot
smtpd_sender_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_non_fqdn_sender, reject_unknown_sender_domain, reject_unknown_reverse_client_hostname
smtpd_timeout = 30s
smtpd_tls_auth_only = yes
smtpd_tls_security_level = may
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_use_tls = yes
strict_rfc821_envelopes = yes
unknown_address_reject_code = 550
unknown_client_reject_code = 550
unknown_hostname_reject_code = 550
unverified_recipient_reject_code = 550
unverified_sender_reject_code = 550
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf, mysql:/etc/postfix/mysql-virtual-email2email.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp

ฉันไม่ได้ทำ SNATing, masquerading หรือ iptables อื่นๆ บนโฮสต์นี้ (ทั้งหมดนี้เกิดขึ้นที่ปลายอีกด้านของอุโมงค์ข้อมูล VPN)

นี่ฉันพลาดอะไรไปหรือเปล่า? เหตุใดจึงมีการรับส่งข้อมูล postfix ขาออกenp1s0แทนที่จะเป็นtun45? และทำไมมันไม่ได้มีแหล่ง IP ที่ตั้งอยู่ในsmtp_bind_address?

answer

นี่เป็นปัญหาการกำหนดค่าในmaster.cf. การกำหนดค่าที่แสดงด้านบน (ในคำถามของฉัน) ตั้งค่าsmtp_bind_addressสำหรับทราฟฟิกขาเข้าเท่านั้น ซึ่งหมายถึง daemons ฟัง

สำหรับทราฟฟิกขาออก หมายถึงเมื่อ postfix daemon ส่งเมลไปยังเซิร์ฟเวอร์อื่น บรรทัดต่อไปนี้ในmaster.cfต้องมีที่อยู่การผูกที่ระบุด้วย ในค่าเริ่มต้น/ตัวอย่างmaster.cfบรรทัดจะมีลักษณะดังนี้:

smtp      unix  -       -       y       -       -       smtp

มันถูกฝังอยู่ใต้พารามิเตอร์อื่นๆ มากมาย ง่ายต่อการพลาด

เปลี่ยนเพื่อเพิ่มที่อยู่ผูกด้วยเช่น:

smtp      unix  -       -       y       -       -       smtp
  -o smtp_bind_address=10.8.0.9

เนื่องจากฉันเรียกใช้ postfix daemons หลายตัวบนเซิร์ฟเวอร์เดียวกันเพื่อให้บริการหลายโดเมนที่มี IP สาธารณะและใบรับรองแยกกัน ฉันจึงเปลี่ยนของฉันเป็น:

outbound_domain1.com unix  -       -       y       -       -       smtp
  -o smtp_bind_address=10.8.0.8
  -o smtp_helo_name=domain1.com

...จากนั้นเพิ่มบรรทัดใน/etc/postfix/sender_transportการแมป daemon ขาออกนี้กับโดเมนอีเมลที่ให้บริการ:

@domain1.com outbound_domain1.com

และแน่นอนว่าคุณต้องบอก postfix ให้ใช้แผนที่การขนส่งนั้นในmain.cf:

sender_dependent_default_transport_maps = hash:/etc/postfix/sender_transport

จากนั้นรันpostmapเพื่อสร้างไฟล์แฮชที่ postfix ใช้สำหรับการค้นหาเหล่านี้

โปรดดูที่คำถามนี้: อีเมลเยี่ยงอย่างป้องกัน Postfix มากกว่าเชื่อมต่อเครือข่ายที่ไม่ถูกต้อง

ในโพสต์นั้น ผู้คนที่ระบุsmtp_bind_addressจะล้มเหลวไปยัง inet_interface อื่น หากไม่มีการกำหนดค่าที่กำหนดค่าไว้ ในกรณีของคุณsmtp_bind_addressชี้ไปที่ IP แบบคงที่ที่ผูกไว้กับ tun0 มันจะผ่านไปทาง tun0 เมื่อมันขึ้น หาก tun0 ไม่ทำงาน การผูกไคลเอ็นต์จะล้มเหลว ทำให้ postfix ถอยกลับไปเป็นพฤติกรรมเริ่มต้นของการไม่ผูกปลายทาง TCP ของไคลเอ็นต์ และจะใช้เส้นทางเริ่มต้นที่เชื่อมต่อกับ eth0