LoginSignup
13
12

More than 5 years have passed since last update.

UDPポートフォワーディング

Last updated at Posted at 2016-04-23

はじめに

TCPのポートフォワーディングはよく見かけるのですが、UDPのポートフォワーディングは用途が限られていることもあるのか、あまり見かけません。
今回は、UDPやソケットの勉強を兼ねてUDPのポートフォワーディングをしたいと思います。

環境

OS X El Capitan
Python 2.7.11
snmpwalk 5.6.2.1

Pythonで実装する

udp_portforwarder.py
import socket
UDP_IP_LISTEN = "192.168.1.12"
UDP_PORT_LISTEN = 161
UDP_IP_TO = "192.168.1.119"
UDP_PORT_TO = 161

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP_LISTEN, UDP_PORT_LISTEN))

src_port = 0

while True:
  data, (host, port) = sock.recvfrom(4096)

  # receive from remote server
  if src_port != 0 and host != UDP_IP_LISTEN:
    sock.sendto(data, (UDP_IP_LISTEN, src_port))
  # send to remote server
  else:
    src_port = port
    sock.sendto(data, (UDP_IP_TO, UDP_PORT_TO))

  print 'forwarded', host, port

解説1
UDPを対象にしたいので、socketにはSOCK_DGRAMを指定。

解説2
bindしたポートには、要求元からと、送付先からの応答と2種類のパケットがrecvfromで届くので、送信元アドレスで条件分岐。

解説3
要求元のポートに返してあげる必要があるので、要求元からのパケットが到着時に要求元ポート番号をsrc_portに格納。

動作確認

  1. tshark udpを実行(パケットの詳細を確認する為)
  2. sudo python udp_capture_portforwarder_remote.pyを実行
  3. snmpwalk -c public -v 1 192.168.1.12を実行

動作結果

snmpwalk
snmpwalk -c public -v 1 192.168.1.12
butada-mac:python_udp_capture_test butada$ snmpwalk -c public -v 1 192.168.1.12
SNMPv2-MIB::sysDescr.0 = STRING: Darwin macbook.local 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.16
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (454525) 1:15:45.25
SNMPv2-MIB::sysContact.0 = STRING: SysAdmin
SNMPv2-MIB::sysName.0 = STRING: SystemName
SNMPv2-MIB::sysLocation.0 = STRING: data centre A
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (4) 0:00:00.04
SNMPv2-MIB::sysORID.1 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBC
<省略>
udp_capture_portforwarder_remote.py
$ sudo python udp_capture_portforwarder_remote.py 
sent to remote snmp
forwarded 192.168.1.12 57598
received from remote snmp
forwarded 192.168.1.119 161
sent to remote snmp
forwarded 192.168.1.12 57598
received from remote snmp
forwarded 192.168.1.119 161
sent to remote snmp
forwarded 192.168.1.12 57598
received from remote snmp
forwarded 192.168.1.119 161
sent to remote snmp
forwarded 192.168.1.12 57598
received from remote snmp
forwarded 192.168.1.119 161
sent to remote snmp
forwarded 192.168.1.12 57598
received from remote snmp
forwarded 192.168.1.119 161
<省略>
tshark
$ tshark udp
1897 2373.448956 192.168.1.12 -> 192.168.1.119 SNMP 82 get-next-request 1.3.6.1.2.1
1898 2373.450958 192.168.1.119 -> 192.168.1.12 SNMP 215 get-response 1.3.6.1.2.1.1.1.0
1899 2373.451207 192.168.1.12 -> 192.168.1.119 SNMP 85 get-next-request 1.3.6.1.2.1.1.1.0
1900 2373.453134 192.168.1.119 -> 192.168.1.12 SNMP 95 get-response 1.3.6.1.2.1.1.2.0
1901 2373.453259 192.168.1.12 -> 192.168.1.119 SNMP 85 get-next-request 1.3.6.1.2.1.1.2.0
1902 2373.454931 192.168.1.119 -> 192.168.1.12 SNMP 88 get-response 1.3.6.1.2.1.1.3.0
1903 2373.455061 192.168.1.12 -> 192.168.1.119 SNMP 85 get-next-request 1.3.6.1.2.1.1.3.0
1904 2373.456796 192.168.1.119 -> 192.168.1.12 SNMP 93 get-response 1.3.6.1.2.1.1.4.0
<省略>

結果

snmpgetを用いて、UDPのポートフォワーディングができることを確認しました。具体的な結果をここに載せられませんでしたが、IPMIについてもipmiutilを使って同様のポートフォワーディングできることを確認できました。

応用

SNMPのパケットキャプチャ&リプレイ

このテクニックを応用して、パケットのキャプチャや、簡易的なスタブを作りました。つまり、フォワーディングする際に記録するのがキャプチャで、そのキャプチャ内容に基づいてフォーワーディングせずに記録した応答を返すのがスタブになります。
http://qiita.com/butada/items/77af324c2a1bb880f101

参考

http://memo.saitodev.com/home/python_network_programing/
http://stackoverflow.com/questions/11350145/are-there-simple-descriptions-on-port-forwarding-using-python
http://stackoverflow.com/questions/2694212/socket-set-source-port-number

13
12
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12