Forum Discussion
SMPP IRULES that insert destination port in One Vip, as Port in Second Vip pool member
I have a 2-step situation with SMPP traffic.
Aggregator Traffic---F5 (VIP 1) 10.1.1.1:* (eg 5102)
F5 (SNAT IP) 10.1.1.2--- SMS FW 10.1.1.3:10000
SMS FW 10.1.1.3--- F5 (VIP 2) 10.1.1.4:10000
F5 (SNAT IP) 10.1.1.2--- SMSC 10.100.114.129:F5 VIP1 destination port (10.100.114.129:5102)
How do i solve this using irules
4 Replies
- Injeyan_Kostas
Cumulonimbus
There is no way to bind dest port in one VS with the pool member port in another VS
Unless you somehow inject this info in to the request itself
If we spoke for http this would be very easy with an http header
In this case I cannot think something else except injecting dest port in to the payload in VIP1 and then in VIP2 extract/strip the value and use it
I am not an SMPP expert so I played with AI
It might not work at all but hope you get the logic.
you can test it and adjust itiRule for VIP 1 (Inject destination port)
when CLIENT_ACCEPTED { # Capture the port this VIP was hit on set injected_port [TCP::local_port] } when CLIENT_DATA { TCP::collect set pdu [TCP::payload] # Extract command_id at offset 4 (should be 0x00000004 for submit_sm) binary scan $pdu @4I cmd_id if { $cmd_id == 4 } { # Inject service_type: P<PORT> + NULL terminator set tag "P$injected_port" set null [binary format c 0] set service_type "$tag$null" # Replace original service_type at offset 16 set new_pdu "${pdu range 0 15}$service_type${pdu range 16 end}" TCP::payload replace 0 [TCP::payload length] $new_pdu log local0. "VIP1: Injected service_type tag $tag into submit_sm" } TCP::release }
iRule for VIP 2 (Extract, route, and clean)
when CLIENT_ACCEPTED { # Init variable set dyn_port 0 } when CLIENT_DATA { TCP::collect set pdu [TCP::payload] # Check SMPP command_id binary scan $pdu @4I cmd_id if { $cmd_id == 4 } { # Read service_type field from byte 16 (C-Octet null-terminated) binary scan $pdu @16Z* service_type # Match and extract port from "P<PORT>" format if {[regexp {^P(\d{1,5})$} $service_type match dyn_port]} { log local0. "VIP2: Extracted dynamic port: $dyn_port" # Strip service_type: replace with single null byte set null [binary format c 0] set tag_len [expr {[string length $service_type] + 1}] set stripped_pdu "${pdu range 0 15}$null${pdu range [expr 16 + $tag_len] end}" TCP::payload replace 0 [TCP::payload length] $stripped_pdu # Set backend IP and dynamic port set backend_ip "10.100.114.129" node $backend_ip $dyn_port log local0. "VIP2: Forwarding to $backend_ip:$dyn_port" } else { log local0. "VIP2: No valid port tag in service_type" } } TCP::release }
- kazeem1
Nimbostratus
Thank you so much. I have played around with the scenario. I also agree with your postulations. My postulation is to add the port into a TLV tag for smpp, and then later pass it through, to be extracted on another irule. I tried the below on VIP 1, AND GOT following logs. I will try your approach and test it. Thanks so much.
when CLIENT_ACCEPTED {
set orig_port [TCP::local_port]
set session_key "[IP::client_addr]:[TCP::client_port]"
set session_data "port=$orig_port"
table set $session_key $session_data 300
set orig_port [TCP::local_port]set session_key "[IP::client_addr]:[TCP::client_port]"
set session_data "port=$orig_port"
table set $session_key $session_data 300
log local0. "VIP1: Client connected from [IP::client_addr]:[TCP::client_port] on original port $orig_port"
}
when CLIENT_DATA {if { [TCP::payload length] < 16 } { return }
binary scan [TCP::payload] I command_lengthif { [TCP::payload length] < $command_length } { return }
binary scan [TCP::payload] x4I command_id x8I seq_numberset min_valid_len 37
if {($command_id == 0x00000009 || $command_id == 0x00000004)
&& [TCP::payload length] >= $min_valid_len
} {
set session_key "[IP::client_addr]:[TCP::client_port]"
set session_data [table lookup $session_key]
if { [string length $session_data] == 0 } {log local0. "VIP1: No session data found for $session_key"
return
}
set orig_port [lindex [split $session_data "="] 1]
# Prepare TLVset tag 0x1401
set tlv_len 2
set value [binary format S $orig_port]
set tlv [binary format SSa* $tag $tlv_len $value]
# Append TLV and update command_lengthset payload [TCP::payload]
set new_len [expr {$command_length + [string length $tlv]}]
# Replace first 4 bytes (command_length)set updated_pdu [binary format I $new_len][string range $payload 4 end]$tlv
# Inject new payloadTCP::payload replace 0 $command_length $updated_pdu
log local0. "VIP1: TLV injected (port=$orig_port). New command_length=$new_len"
}
}
when CLIENT_CLOSED {
log local0. "VIP1: Client [IP::client_addr]:[TCP::client_port] closed connection"
table delete "[IP::client_addr]:[TCP::client_port]"
}
when SERVER_CLOSED {log local0. "VIP1: SMS Firewall [IP::server_addr]:[TCP::server_port] closed connection"
}
Jun 4 04:36:21 unotelossaka.gloworld.com info tmm[18939]: Rule /Common/smsc1 <CLIENT_DATA>: VIP2: Expected TLV 0x1401 not found for 00000009. Using default port 10000.
Jun 4 04:36:21 unotelossaka.gloworld.com info tmm[18939]: Rule /Common/smsc1 <CLIENT_DATA>: VIP2: SERVER not yet connected; deferring node assignment
Jun 4 04:36:33 unotelossaka.gloworld.com info tmm[18939]: Rule /Common/smpp1 <CLIENT_CLOSED>: VIP1: Client 193.135.101.16:16715 closed connection
Jun 4 04:36:33 unotelossaka.gloworld.com info tmm[18939]: Rule /Common/smpp1 <SERVER_CLOSED>: VIP1: SMS Firewall 10.159.59.132:10000 closed connection
Jun 4 04:36:33 unotelossaka.gloworld.com info tmm[18939]: Rule /Common/smpp1 <CLIENT_CLOSED>: VIP1: Client 193.135.101.16:56925 closed connection
Jun 4 04:36:33 unotelossaka.gloworld.com info tmm[18939]: Rule /Common/smpp1 <SERVER_CLOSED>: VIP1: SMS Firewall 10.159.59.132:10000 closed connection
Jun 4 04:36:43 unotelossaka.gloworld.com info tmm2[18939]: Rule /Common/smpp1 <CLIENT_ACCEPTED>: VIP1: Client connected from 193.135.101.16:45599 on original port 5102
Jun 4 04:36:43 unotelossaka.gloworld.com info tmm3[18939]: Rule /Common/smpp1 <CLIENT_ACCEPTED>: VIP1: Client connected from 193.135.101.16:29867 on original port 5102
Jun 4 04:36:45 unotelossaka.gloworld.com info tmm1[18939]: Rule /Common/smsc1 <CLIENT_ACCEPTED>: VIP2: Connection received from SMS Firewall from 10.159.59.132:39024
Jun 4 04:36:45 unotelossaka.gloworld.com info tmm1[18939]: Rule /Common/smsc1 <CLIENT_DATA>: VIP2: Processing command: 00000009 (Length: 37)
Jun 4 04:36:45 unotelossaka.gloworld.com info tmm1[18939]: Rule /Common/smsc1 <CLIENT_DATA>: VIP2: Expected TLV 0x1401 not found for 00000009. Using default port 10000. - kazeem1
Nimbostratus
So,Injeyan, Thank you for your irule. It is fantstic for submit_sm. before the submit_sm, there is the bind_transceiver which is my primary concern. The service is supposed to be for bind_transceiver (0x00000009) and submit_sm (0x00000004). is there a way to write custom TLV to insert destination ports inside and push it inside pdu? Thanks
- Injeyan_Kostas
Cumulonimbus
Thanks but as said have no idea about SMPP.
I just found this case interesting, understood a concept that might be able to work, and gave the relevant prompts to AI.
So i will try to understand how this flow works and might think something.
In the meantime lets see if there is anyone with more knowledge in this matter.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com