crotchmaster
happy BSD user
Moin Jungs,
ich bin seit einiger Zeit dabei, einer OpenBSD-FW aus zwei Maschinen mit einer S-DSL und einer A-DSL Leitung das Loadbalancing beizubringen. Für die 'normalen' Verbindungen klappt das auch ganz gut.
Das Problem sind Verbindungen, die über transparente Proxies laufen.
Laut pf-FAQ, werden die ausgehende IP-Adresse und das ausgehende Interface, im Prinzip also die Route, über eine pass-Regel auf dem Eingangsinterface der FW festgelegt. Bei den normalen Verbindungen klappt das auch gut. Bei Verbindungen, die über Proxies gehen, 'enden' diese auf dem internen Interface und der Proxy macht eine neue Verbindung nach aussen auf. Deshalb geht das normale Prozedere aus der FAQ nicht.
Meine Idee war nun, ich setze zwei Proxies (squid) auf. Einer lauscht auf 127.0.0.1:3128 und der andere auf 127.0.0.2:3128 und verteile die eingehenden Anfragen an port 80 auf dem internen Interface mittels rdr-Regel abwechselnd auf die beiden Proxies. Die Proxies sind so konfiguriert, dass sie jeweils eine eigene ausgehende IP-Adresse (tcp_outgoing_address im Bsp. 192.168.0.1 und 192.168.0.2) haben. Abhängig von der ausgehenden IP-Adresse sollen unterschiedliche NAT-Rules wirksam werden.
Und hier scheitere ich. Die Verteilung auf die beiden Proxies klappt, die unterschiedlichen ausgehenden IP-Adressen werden dann aber nur auf die erste gemeinsame IP-Adresse, im Bsp. auf die 1.2.3.3 übersetzt und gehen dann über die Standardroute raus. Das ist die S-DSL Leitung.
Hier mal das aufs Wesentliche beschränkte Regelwerk:
Die in den Kommentaren beigefügten IP-Adressen sind nicht die echten, spiegeln aber den Aufbau des System 1:1 wieder.
Ich hoffe, das mir jemand einen Tipp geben kann, woran es liegt. Ich tippe auf die NAT-Regeln und übersehe da wohl etwas. Nur was?
Kann außerdem jemand bestätigen, dass das Prinzip 'last matching rule wins' bei NAT nicht greift? Das ist nämlich meine Beobachtung mittels pfctl.
Danke und Gruß
c.
ich bin seit einiger Zeit dabei, einer OpenBSD-FW aus zwei Maschinen mit einer S-DSL und einer A-DSL Leitung das Loadbalancing beizubringen. Für die 'normalen' Verbindungen klappt das auch ganz gut.
Das Problem sind Verbindungen, die über transparente Proxies laufen.
Laut pf-FAQ, werden die ausgehende IP-Adresse und das ausgehende Interface, im Prinzip also die Route, über eine pass-Regel auf dem Eingangsinterface der FW festgelegt. Bei den normalen Verbindungen klappt das auch gut. Bei Verbindungen, die über Proxies gehen, 'enden' diese auf dem internen Interface und der Proxy macht eine neue Verbindung nach aussen auf. Deshalb geht das normale Prozedere aus der FAQ nicht.
Meine Idee war nun, ich setze zwei Proxies (squid) auf. Einer lauscht auf 127.0.0.1:3128 und der andere auf 127.0.0.2:3128 und verteile die eingehenden Anfragen an port 80 auf dem internen Interface mittels rdr-Regel abwechselnd auf die beiden Proxies. Die Proxies sind so konfiguriert, dass sie jeweils eine eigene ausgehende IP-Adresse (tcp_outgoing_address im Bsp. 192.168.0.1 und 192.168.0.2) haben. Abhängig von der ausgehenden IP-Adresse sollen unterschiedliche NAT-Rules wirksam werden.
Und hier scheitere ich. Die Verteilung auf die beiden Proxies klappt, die unterschiedlichen ausgehenden IP-Adressen werden dann aber nur auf die erste gemeinsame IP-Adresse, im Bsp. auf die 1.2.3.3 übersetzt und gehen dann über die Standardroute raus. Das ist die S-DSL Leitung.
Hier mal das aufs Wesentliche beschränkte Regelwerk:
Code:
###############
# definitions #
###############
## interface definitions ##
# external interface 1 - IP-Adresse 1.2.3.1
extIf1 = "de0"
# external carp interface 1 - IP-Adresse 1.2.3.3
extCarpIf1 = "carp0"
# external interface 2 - IP-Adresse 4.3.2.1
extIf2 = "de1"
# external carp interface 2 - IP-Adresse 4.3.2.3
extCarpIf2 = "carp1"
# internal interface - IP-Adresse 192.168.0.1 (hat zusätzlich einen alias 192.168.0.2/32)
intIf = "de2"
# internal carp interface - IP-Adresse 192.168.0.5
intCarpIf = "carp2"
# pfsync interface - 192.168.1.1
pfsyncIf = "de3"
# loopback interface - IP-Adresse 127.0.0.1 (hat zusätzlich einen alias 127.0.0.2/32)
loopIf = "lo0"
# logging interface
logIf = "$extIf1"
## networks ##
# internal networks
table <intNet> const { 192.168.0.0/26, 192.168.0.64/26, 192.168.0.128/26 }
## gateway definitions ##
# S-DSL Router
extGw1="1.2.3.4"
# A-DSL Router
extGw2="4.3.2.4"
###########
# options #
###########
set skip on $loopIf
set skip on $pfsyncIf
set block-policy return
set state-policy if-bound
set loginterface $intIf
set limit { states 60000, frags 60000 }
set optimization normal
set timeout interval 15
set timeout frag 30
set timeout src.track 900
# Clean up fragmented and abnormal packets
# By default in pf, packets which contain IP options are blocked. Good.
scrub in on { $extIf1, $extIf2 } all fragment reassemble
##################################
# nat rules for outgoing packets #
##################################
nat-anchor "ftp-proxy/*"
nat on $extIf1 inet from 192.168.0.1 to any port 80 -> $extCarpIf1:0 source-hash
nat on $extIf2 inet from 192.168.0.2 to any port 80 -> $extCarpIf2:0 source-hash
nat on $extIf1 inet from <intNet> to any -> $extCarpIf1:0 source-hash
nat on $extIf2 inet from <intNet> to any -> $extCarpIf2:0 source-hash
###########################################
# redirect rules for incoming connections #
###########################################
# redirect incoming http connections to squid proxy
rdr on $intIf proto tcp from <intNet> to any port 80 -> { 127.0.0.1, 127.0.0.2 } port 3128 round-robin sticky-address
#####################################
# immediate blocking and pass rules #
#####################################
# blocking spoofed packets
antispoof log for $extIf1 inet
antispoof log for $extIf2 inet
antispoof log for $intIf inet
# pass carp communication
pass quick on { $intIf $extIf1 $extIf2 } proto carp keep state
# block and log everything
block out log all
block in log all
# fuzz any 'nmap' attempt
block in quick log on { $intIf, $extIf1, $extIf2 } inet proto tcp from any to any flags FUP/FUP
block in quick log on { $intIf, $extIf1, $extIf2 } inet proto tcp from any to any flags SF/SFRA
block in quick log on { $intIf, $extIf1, $extIf2 } inet proto tcp from any to any flags /SFRA
# block anything coming from source we have no back routes for
block in from no-route to any
################################################
# incoming connections on internal interface #
################################################
# allow incoming http connections (port 3128)
pass in on $intIf proto tcp from <intNet> to any port 3128 keep state
# allow incoming ssh connections (port 22)
pass in on $intIf route-to { ($extIf1 $extGw1), ($extIf2 $extGw2) } round-robin proto tcp from <intNet> to any port ssh keep state
########################
# outgoing Connections #
########################
# allow all other connections without load balancing
pass out on { $intIf, $extIf1, $extIf2 } proto tcp all modulate state flags S/SA
pass out on { $intIf, $extIf1, $extIf2 } proto { udp, icmp } all keep state
pass out on $extIf1 route-to ($extIf2 $extGw2) from $extIf2
pass out on $extIf2 route-to ($extIf1 $extGw1) from $extIf1
Ich hoffe, das mir jemand einen Tipp geben kann, woran es liegt. Ich tippe auf die NAT-Regeln und übersehe da wohl etwas. Nur was?
Kann außerdem jemand bestätigen, dass das Prinzip 'last matching rule wins' bei NAT nicht greift? Das ist nämlich meine Beobachtung mittels pfctl.
Danke und Gruß
c.