How can I force the LTM SOCKS Service to send connect requests out a specific interface?
Hello,
I've set up an LTM running 11.6 to act as an stunnel server (see stunnel.org). A client on the Internet is configured as an stunnel client. The stunnel client is listening on TCP port 1080 for SOCKS requests from other hosts on the stunnel client's local network. When a SOCKSified browser on one of those other hosts attempts to visit a web site, the request is sent to the stunnel client, which sets up an SSL connection to the stunnel server (LTM). The LTM forwards the SOCKS traffic inside the SSL connection to a SOCKS service on the same LTM, where it is subject to a whitelist implemented via an iRule and Data Group.
Network configuration is as follows:
[Host with SOCKSified browser]----[stunnel client]----[Internet]----[Outside Firewall]a----b[BigIP LTM]c-----d[Inside Firewall]----[Inside Network]
Where
- a = 11.12.13.225 external firewall's inside IP address
- b = 11.12.13.226 LTM's external IP address
- c = 10.239.127.40 LTM's internal IP address
- d = 10.239.127.33 internal firewall's outside IP address
This all works fine.
Now, I want to modify the LTM configuration such that the outbound connect requests from the LTM's SOCKS service are always sent out the LTM's internal interface through the inside firewall rather than out whatever interface the LTM's route table dictates.
Problem:This situation seemed to me to call for an additional route domain. So, I configured a second route domain (1) and added the inside interface of the LTM to it, added a default route in that second domain with a next hop of (d), and I configured the SOCKS service to use this route domain, but outbound connect requests for external hosts still traverse the LTM's outside interface. I'd appreciate any pointers.
Configuration:admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm virtual vs_230_STUNNEL-self_SOCKS
ltm virtual vs_230_STUNNEL-self_SOCKS {
description ""
destination 11.12.13.230:9443
ip-protocol tcp
mask 255.255.255.255
profiles {
g4vip230_SSL {
context clientside
}
tcp { }
}
rules {
irule_log_SSL
irule_self_SOCKS
}
source 0.0.0.0/0
source-address-translation {
type automap
}
vs-index 6
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm virtual vs_self_SOCKS
ltm virtual vs_self_SOCKS {
description ""
destination 11.12.13.130:socks
ip-protocol tcp
mask 255.255.255.255
profiles {
self_SOCKS { }
tcp { }
}
rules {
irule_whitelist_SOCKS
}
source 0.0.0.0/0
source-address-translation {
type automap
}
vlans-enabled
vs-index 5
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm rule irule_whitelist_SOCKS
ltm rule irule_whitelist_SOCKS {
when SOCKS_REQUEST {
if { [class match [SOCKS::destination] ends_with SOCKS_whitelist] } {
log -noname local6.notice "[virtual name]: SOCKS request from client at [IP::remote_addr] for host [SOCKS::destination] allowed"
SOCKS::allowed 1
} else {
log -noname local6.warning "[virtual name]: SOCKS request from client at [IP::remote_addr] for host [SOCKS::destination] blocked"
SOCKS::allowed 0
}
}
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm profile socks
ltm profile socks self_SOCKS {
app-service none
default-connect-handling allow
defaults-from socks
dns-resolver self_DNS
protocol-versions { socks4 socks4a socks5 }
route-domain rd_internal
tunnel-name socks-tunnel
}
ltm profile socks socks {
app-service none
default-connect-handling deny
protocol-versions { socks4 socks4a socks5 }
route-domain 0
tunnel-name socks-tunnel
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm rule irule_log_SSL
ltm rule irule_log_SSL {
when CLIENTSSL_CLIENTCERT {
This event is triggered when LTM requests/requires a cert, even if the client doesn't present a cert.
Check if client presented a cert after it was requested/required
if {[SSL::cert count] > 0}{
Client presented at least one cert. The actual client cert should always be first.
Loop through each cert and log the cert subject, issuer and serial number
for {set i 0} {$i < [SSL::cert count]} {incr i}{
log -noname local6.notice "[virtual name]: Client [IP::client_addr]:[TCP::client_port] SSL handshake: Received cert [expr {1 + $i}] of [SSL::cert count] - Subject: [X509::subject [SSL::cert $i]];\
Issuer: [X509::issuer [SSL::cert $i]]; Serial: [X509::serial_number [SSL::cert $i]];"
}
set cert_error [X509::verify_cert_error_string [SSL::verify_result]]
if { [info exists cert_error] } {
if { not ([string tolower $cert_error] ends_with "ok") } {
log -noname local6.error "[virtual name]: Client [IP::client_addr]:[TCP::client_port] SSL handshake failed: $cert_error"
}
}
} else {
log -noname local6.error "[virtual name]: Client [IP::client_addr]:[TCP::client_port] SSL handshake failed: Client did not provide a certificate"
}
}
when CLIENTSSL_HANDSHAKE {
log -noname local6.notice "[virtual name]: Client [IP::client_addr]:[TCP::client_port] SSL handshake successful: Session ID [SSL::sessionid]"
}
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list ltm rule irule_self_SOCKS
ltm rule irule_self_SOCKS {
when CLIENT_ACCEPTED {
virtual /Common/vs_self_SOCKS
}
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list net route-domain
net route-domain 0 {
id 0
vlans {
http-tunnel
socks-tunnel
external
}
}
net route-domain rd_internal {
id 1
strict disabled
vlans {
internal
}
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list net route
net route external_default_gateway {
gw 11.12.13.225
network default
}
net route internal_default_gateway {
gw 10.239.127.33%1
network default%1
}
admin@(vira231g4)(cfg-sync Standalone)(Active)(/Common)(tmos) list net self
net self 10.239.127.40 {
address 10.239.127.40%1/27
traffic-group traffic-group-local-only
vlan internal
}
net self 11.12.13.226 {
address 11.12.13.226/28
traffic-group traffic-group-local-only
vlan external
}