Transparent proxy#
SNMP Proxy Forwarder can turn fully stealth meaning that neither frontend SNMP managers nor backend SNMP agents are aware of the proxy existence in between them.
The workflow scenario could be like this:
SNMP managers send SNMP queries to SNMP agents they know about
The network routes request packets from SNMP managers to the SNMP Proxy Forwarder host where its server part is running
The request gets forwarded to the client part which then sends it towards SNMP agent:
to the destination address originally used by SNMP manager
spoofing source address to the SNMP manager’s one
The network routes response packets from SNMP agent destined to SNMP manager address to the SNMP Proxy Forwarder host where its client part is running
This only works on Linux, requires Python 3.3+ and superuser privileges.
Network configuration#
You need to configure your network routing in a way that SNMP packets being sent by SNMP managers towards SNMP agents are routed to the host where the server part of SNMP Proxy Forwarder is listening.
At that host, the following iptables configuration is suggested:
# setup a chain DIVERT to mark packets
iptables -t mangle -N DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
# use DIVERT to prevent packets bound to open socket going through TPROXY twice
iptables -t mangle -A PREROUTING -p udp -m socket -j DIVERT
# mark all other (new) packets and use TPROXY to pass into snmpfwd listening at port 161
iptables -t mangle -A PREROUTING -p udp --dport 161 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 161
Once we have incoming SNMP packets identified, we need to source-route them to the server part of SNMP proxy listening on lo:
ip route flush table 100
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
In some use-cases, packet forwarding should be enabled on the system:
echo 1 > /proc/sys/net/ipv4/ip_forward
For more information on Linux kernel TPROXY operation, please refer to the Linux kernel documentation.
Server configuration#
Server is configured to:
listen on UDP socket at localhost
turn UDP socket into transparent-proxy mode
respond to queries performed over SNMPv2c
forward all queries to snmpfwd client through an unencrypted trunk connection running in client mode
#
# SNMP forwarder: Agent part configuration
#
config-version: 2
program-name: snmpfwd-server
snmp-credentials-group {
snmp-engine-id: 0x0102030405070809
snmp-community-name: public
snmp-security-name: public
snmp-security-model: 2
snmp-security-level: 1
# Note: additional iptables configuration is required for transparent operation
snmp-transport-domain: 1.3.6.1.6.1.1.100
# enable source IP address spoofing as well as receiving packets
# destined to any IP, even not present on this system
snmp-transport-options: transparent-proxy
snmp-bind-address: 127.0.0.1:1161
snmp-credentials-id: snmp-credentials
}
context-group {
snmp-context-engine-id-pattern: .*?
snmp-context-name-pattern: .*?
snmp-context-id: any-context
}
content-group {
snmp-pdu-type-pattern: .*?
snmp-pdu-oid-prefix-pattern-list: .*?
snmp-content-id: any-content
}
peers-group {
snmp-transport-domain: 1.3.6.1.6.1.1.100
snmp-bind-address-pattern-list: .*?
snmp-peer-address-pattern-list: .*?
snmp-peer-id: 100
}
trunking-group {
trunk-bind-address: 127.0.0.1
trunk-peer-address: 127.0.0.1:30301
trunk-ping-period: 60
trunk-connection-mode: client
trunk-id: trunk-1
}
routing-map {
matching-snmp-context-id-list: any-context
matching-snmp-content-id-list: any-content
matching-snmp-credentials-id-list: snmp-credentials
matching-snmp-peer-id-list: 100
using-trunk-id-list: trunk-1
}
Download
server configuration file.
Client configuration#
Client is configured to:
listen on server-mode unencrypted trunk connection
turn UDP socket it uses for communicating with SNMP agents into transparent-proxy mode
place inbound PDUs into SNMP v2c messages and forward them to the address that SNMP manager used when sending packets to the server part
spoof source address of the packets to the address of SNMP manager which sends the query
#
# SNMP forwarder: Manager part configuration
#
config-version: 2
program-name: snmpfwd-client
peers-group {
snmp-engine-id: 0x0102030405070809
snmp-transport-domain: 1.3.6.1.6.1.1.1
# time out SNMP request in 1 second
snmp-peer-timeout: 100
snmp-peer-retries: 0
snmp-community-name: public
snmp-security-name: public
snmp-security-model: 2
snmp-security-level: 1
# Note: additional iptables configuration is required for transparent operation
# enable source IP address spoofing as well as receiving packets
# destined to any IP, even not present on this system
snmp-transport-options: transparent-proxy
# spoof source IP to the IP of the SNMP manager talking to the server part
snmp-bind-address: ${snmp-peer-address}
# send packets to the IP that SNMP manager originally sent them to
snmp-peer-address: ${snmp-bind-address}
snmp-peer-id: any-agent
}
trunking-group {
trunk-bind-address: 127.0.0.1:30301
trunk-ping-period: 60
trunk-connection-mode: server
trunk-id: <discover>
}
original-snmp-peer-info-group {
orig-snmp-bind-address-pattern: .*?
orig-snmp-context-name-pattern: .*?
orig-snmp-pdu-type-pattern: .*?
orig-snmp-oid-prefix-pattern: .*?
orig-snmp-engine-id-pattern: .*?
orig-snmp-context-engine-id-pattern: .*?
orig-snmp-transport-domain-pattern: .*?
orig-snmp-peer-address-pattern: .*?
orig-snmp-security-level-pattern: .*?
orig-snmp-security-name-pattern: .*?
orig-snmp-security-model-pattern: .*?
orig-snmp-peer-id: any-manager
}
server-classification-group {
server-snmp-credentials-id-pattern: .*?
server-snmp-context-id-pattern: .*?
server-snmp-content-id-pattern: .*?
server-snmp-peer-id-pattern: .*?
server-classification-id: any-classification
}
routing-map {
matching-trunk-id-list: trunk-1
matching-orig-snmp-peer-id-list: any-manager
matching-server-classification-id-list: any-classification
using-snmp-peer-id-list: any-agent
}
Download
client configuration file.