CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/natpmp/packet.rb
Views: 11704
1
# -*- coding: binary -*-
2
##
3
#
4
# NAT-PMP protocol support
5
#
6
##
7
8
module Rex
9
module Proto
10
module NATPMP::Packet
11
12
# Return a NAT-PMP request to get the external address.
13
def external_address_request
14
[ 0, 0 ].pack('nn')
15
end
16
17
def get_external_address(udp_sock, host, port, timeout=1)
18
vprint_status("#{host}:#{port} - Probing NAT-PMP for external address")
19
udp_sock.sendto(external_address_request, host, port, 0)
20
external_address = nil
21
while (r = udp_sock.recvfrom(12, timeout) and r[1])
22
(ver, op, result, epoch, external_address) = parse_external_address_response(r[0])
23
if external_address
24
vprint_good("#{host}:#{port} - NAT-PMP external address is #{external_address}")
25
break
26
end
27
end
28
external_address
29
end
30
31
# Parse a NAT-PMP external address response +resp+.
32
# Returns the decoded parts of the response as an array.
33
def parse_external_address_response(resp)
34
(ver, op, result, epoch, addr) = resp.unpack("CCnNN")
35
[ ver, op, result, epoch, Rex::Socket::addr_itoa(addr) ]
36
end
37
38
def map_port(udp_sock, host, port, int_port, ext_port, protocol, lifetime, timeout=1)
39
vprint_status("#{host}:#{port} - Sending NAT-PMP mapping request")
40
# build the mapping request
41
req = map_port_request(int_port, ext_port,
42
Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), datastore['LIFETIME'])
43
# send it
44
udp_sock.sendto(req, host, datastore['RPORT'], 0)
45
# handle the reply
46
while (r = udp_sock.recvfrom(16, timeout) and r[1])
47
(_, _, result, _, _, actual_ext_port, _) = parse_map_port_response(r[0])
48
return (result == 0 ? actual_ext_port : nil)
49
end
50
nil
51
end
52
53
# Return a NAT-PMP request to map remote port +rport+/+protocol+ to local port +lport+ for +lifetime+ ms
54
def map_port_request(lport, rport, protocol, lifetime)
55
[ Rex::Proto::NATPMP::Version, # version
56
protocol, # opcode, which is now the protocol we are asking to forward
57
0, # reserved
58
lport,
59
rport,
60
lifetime
61
].pack("CCnnnN")
62
end
63
64
# Parse a NAT-PMP mapping response +resp+.
65
# Returns the decoded parts as an array.
66
def parse_map_port_response(resp)
67
resp.unpack("CCnNnnN")
68
end
69
70
end
71
72
end
73
end
74
75