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.