mirror of
https://github.com/nmap/nmap.git
synced 2025-12-14 19:59:02 +00:00
Committing MTU-related changes:
* Adding path-mtu.nse for Path MTU Discovery * Nmap now stores the MTU for interfaces (from SIOCGIFMTU or libdnet) * Scripts can access the MTU for host.interface via host.interface_mtu * Nmap prints the MTU for interfaces in --iflist
This commit is contained in:
11
CHANGELOG
11
CHANGELOG
@@ -1,5 +1,16 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added the path-mtu script to perform Path MTU Discovery to the
|
||||||
|
target host using TCP or UDP. The script tries to conserve bandwidth and
|
||||||
|
time by starting with the outgoing interface's MTU and properly handling
|
||||||
|
the Next-Hop MTU field in ICMP responses generated by RFC-compliant
|
||||||
|
intermediate routers. [Kris]
|
||||||
|
|
||||||
|
o [NSE] Scripts can now access the MTU of the host.interface device using
|
||||||
|
host.interface_mtu. [Kris]
|
||||||
|
|
||||||
|
o Nmap now prints the MTU for interfaces when using --iflist. [Kris]
|
||||||
|
|
||||||
o [NSE] Removed references to MD2, as OpenSSL 1.x.x doesn't support it anymore
|
o [NSE] Removed references to MD2, as OpenSSL 1.x.x doesn't support it anymore
|
||||||
[alexandru]
|
[alexandru]
|
||||||
|
|
||||||
|
|||||||
14
Target.cc
14
Target.cc
@@ -133,8 +133,9 @@ void Target::Initialize() {
|
|||||||
htn.toclock_running = false;
|
htn.toclock_running = false;
|
||||||
htn.host_start = htn.host_end = 0;
|
htn.host_start = htn.host_end = 0;
|
||||||
interface_type = devt_other;
|
interface_type = devt_other;
|
||||||
devname[0] = '\0';
|
devname[0] = '\0';
|
||||||
devfullname[0] = '\0';
|
devfullname[0] = '\0';
|
||||||
|
mtu = 0;
|
||||||
state_reason_init(&reason);
|
state_reason_init(&reason);
|
||||||
memset(&pingprobe, 0, sizeof(pingprobe));
|
memset(&pingprobe, 0, sizeof(pingprobe));
|
||||||
pingprobe_state = PORT_UNKNOWN;
|
pingprobe_state = PORT_UNKNOWN;
|
||||||
@@ -378,6 +379,15 @@ void Target::setNextHop(struct sockaddr_storage *next_hop, size_t next_hop_len)
|
|||||||
nexthopsocklen = next_hop_len;
|
nexthopsocklen = next_hop_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set MTU (to correspond with devname) */
|
||||||
|
void Target::setMTU(int devmtu) {
|
||||||
|
mtu = devmtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get MTU (to correspond with devname) */
|
||||||
|
int Target::MTU(void) {
|
||||||
|
return mtu;
|
||||||
|
}
|
||||||
|
|
||||||
/* Starts the timeout clock for the host running (e.g. you are
|
/* Starts the timeout clock for the host running (e.g. you are
|
||||||
beginning a scan). If you do not have the current time handy,
|
beginning a scan). If you do not have the current time handy,
|
||||||
|
|||||||
6
Target.h
6
Target.h
@@ -225,6 +225,9 @@ class Target {
|
|||||||
next_hop has never been set */
|
next_hop has never been set */
|
||||||
bool nextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len);
|
bool nextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len);
|
||||||
|
|
||||||
|
void setMTU(int devmtu);
|
||||||
|
int MTU(void);
|
||||||
|
|
||||||
/* Sets the interface type to one of:
|
/* Sets the interface type to one of:
|
||||||
devt_ethernet, devt_loopback, devt_p2p, devt_other
|
devt_ethernet, devt_loopback, devt_p2p, devt_other
|
||||||
*/
|
*/
|
||||||
@@ -318,7 +321,8 @@ class Target {
|
|||||||
struct host_timeout_nfo htn;
|
struct host_timeout_nfo htn;
|
||||||
devtype interface_type;
|
devtype interface_type;
|
||||||
char devname[32];
|
char devname[32];
|
||||||
char devfullname[32];
|
char devfullname[32];
|
||||||
|
int mtu;
|
||||||
/* 0 (OS_NOTPERF) if os detection not performed
|
/* 0 (OS_NOTPERF) if os detection not performed
|
||||||
* 1 (OS_PERF) if os detection performed
|
* 1 (OS_PERF) if os detection performed
|
||||||
* 2 (OS_PERF_UNREL) if an unreliable os detection has been performed */
|
* 2 (OS_PERF_UNREL) if an unreliable os detection has been performed */
|
||||||
|
|||||||
@@ -1513,6 +1513,15 @@ LUALIB_API int luaopen_openssl(lua_State *L) {
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>host.interface_mtu</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>The MTU (maximum transmission unit) for <literal>host.interface</literal>,
|
||||||
|
or 0 if not known.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>host.bin_ip</option>
|
<term><option>host.bin_ip</option>
|
||||||
</term>
|
</term>
|
||||||
|
|||||||
@@ -995,6 +995,8 @@ static int collect_dnet_interfaces(const struct intf_entry *entry, void *arg) {
|
|||||||
dcrn->ifaces[dcrn->numifaces].device_type = devt_other;
|
dcrn->ifaces[dcrn->numifaces].device_type = devt_other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dcrn->ifaces[dcrn->numifaces].mtu = entry->intf_mtu;
|
||||||
|
|
||||||
/* Is the interface up and running? */
|
/* Is the interface up and running? */
|
||||||
dcrn->ifaces[dcrn->numifaces].device_up = (entry->intf_flags & INTF_FLAG_UP) ? true : false;
|
dcrn->ifaces[dcrn->numifaces].device_up = (entry->intf_flags & INTF_FLAG_UP) ? true : false;
|
||||||
|
|
||||||
@@ -1197,6 +1199,27 @@ static struct interface_info *getinterfaces_siocgifconf(int *howmany, char *errs
|
|||||||
else
|
else
|
||||||
devs[count].device_up = 0;
|
devs[count].device_up = 0;
|
||||||
|
|
||||||
|
#ifdef SIOCGIFMTU
|
||||||
|
memcpy(&tmpifr.ifr_addr, sin, MIN(sizeof(tmpifr.ifr_addr), sizeof(*sin)));
|
||||||
|
rc = ioctl(sd, SIOCGIFMTU, &tmpifr);
|
||||||
|
if (rc < 0) {
|
||||||
|
if(errstr) Snprintf(errstr, errstrlen, "Failed to determine the mtu of %s!", tmpifr.ifr_name);
|
||||||
|
*howmany=-1;
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
#ifdef ifr_mtu
|
||||||
|
devs[count].mtu = tmpifr.ifr_mtu;
|
||||||
|
#else
|
||||||
|
/* Some systems lack ifr_mtu and a common solution (see pcap, dnet and
|
||||||
|
* others) is using ifr_metric instead
|
||||||
|
*/
|
||||||
|
devs[count].mtu = tmpifr.ifr_metric;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
devs[count].mtu = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* All done with this interface. Increase the count. */
|
/* All done with this interface. Increase the count. */
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ struct interface_info {
|
|||||||
u16 netmask_bits; /* CIDR-style. So 24 means class C (255.255.255.0)*/
|
u16 netmask_bits; /* CIDR-style. So 24 means class C (255.255.255.0)*/
|
||||||
devtype device_type; /* devt_ethernet, devt_loopback, devt_p2p, devt_other */
|
devtype device_type; /* devt_ethernet, devt_loopback, devt_p2p, devt_other */
|
||||||
int device_up; /* True if the device is up (enabled) */
|
int device_up; /* True if the device is up (enabled) */
|
||||||
|
int mtu; /* Interface's MTU size */
|
||||||
u8 mac[6]; /* Interface MAC address if device_type is devt_ethernet */
|
u8 mac[6]; /* Interface MAC address if device_type is devt_ethernet */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ void set_hostinfo(lua_State *L, Target *currenths) {
|
|||||||
lua_setfield(L, -2, "mac_addr_src");
|
lua_setfield(L, -2, "mac_addr_src");
|
||||||
}
|
}
|
||||||
setsfield(L, -1, "interface", currenths->deviceName());
|
setsfield(L, -1, "interface", currenths->deviceName());
|
||||||
|
setnfield(L, -1, "interface_mtu", currenths->MTU());
|
||||||
if ((u32)(currenths->v4host().s_addr))
|
if ((u32)(currenths->v4host().s_addr))
|
||||||
{
|
{
|
||||||
struct in_addr adr = currenths->v4host();
|
struct in_addr adr = currenths->v4host();
|
||||||
|
|||||||
@@ -336,13 +336,14 @@ int print_iflist(void) {
|
|||||||
if (o.debugging)
|
if (o.debugging)
|
||||||
log_write(LOG_STDOUT, "Reason: %s\n", errstr);
|
log_write(LOG_STDOUT, "Reason: %s\n", errstr);
|
||||||
} else {
|
} else {
|
||||||
int devcol = 0, shortdevcol = 1, ipcol = 2, typecol = 3, upcol = 4, maccol = 5;
|
int devcol = 0, shortdevcol = 1, ipcol = 2, typecol = 3, upcol = 4, mtucol = 5, maccol = 6;
|
||||||
Tbl = new NmapOutputTable(numifs + 1, 6);
|
Tbl = new NmapOutputTable(numifs + 1, 7);
|
||||||
Tbl->addItem(0, devcol, false, "DEV", 3);
|
Tbl->addItem(0, devcol, false, "DEV", 3);
|
||||||
Tbl->addItem(0, shortdevcol, false, "(SHORT)", 7);
|
Tbl->addItem(0, shortdevcol, false, "(SHORT)", 7);
|
||||||
Tbl->addItem(0, ipcol, false, "IP/MASK", 7);
|
Tbl->addItem(0, ipcol, false, "IP/MASK", 7);
|
||||||
Tbl->addItem(0, typecol, false, "TYPE", 4);
|
Tbl->addItem(0, typecol, false, "TYPE", 4);
|
||||||
Tbl->addItem(0, upcol, false, "UP", 2);
|
Tbl->addItem(0, upcol, false, "UP", 2);
|
||||||
|
Tbl->addItem(0, mtucol, false, "MTU", 3);
|
||||||
Tbl->addItem(0, maccol, false, "MAC", 3);
|
Tbl->addItem(0, maccol, false, "MAC", 3);
|
||||||
for (i = 0; i < numifs; i++) {
|
for (i = 0; i < numifs; i++) {
|
||||||
Tbl->addItem(i + 1, devcol, false, iflist[i].devfullname);
|
Tbl->addItem(i + 1, devcol, false, iflist[i].devfullname);
|
||||||
@@ -366,6 +367,7 @@ int print_iflist(void) {
|
|||||||
Tbl->addItem(i + 1, typecol, false, "other");
|
Tbl->addItem(i + 1, typecol, false, "other");
|
||||||
Tbl->addItem(i + 1, upcol, false,
|
Tbl->addItem(i + 1, upcol, false,
|
||||||
(iflist[i].device_up ? "up" : "down"));
|
(iflist[i].device_up ? "up" : "down"));
|
||||||
|
Tbl->addItemFormatted(i + 1, mtucol, false, "%d", iflist[i].mtu);
|
||||||
}
|
}
|
||||||
log_write(LOG_PLAIN, "************************INTERFACES************************\n");
|
log_write(LOG_PLAIN, "************************INTERFACES************************\n");
|
||||||
log_write(LOG_PLAIN, "%s\n", Tbl->printableTable(NULL));
|
log_write(LOG_PLAIN, "%s\n", Tbl->printableTable(NULL));
|
||||||
|
|||||||
391
scripts/path-mtu.nse
Normal file
391
scripts/path-mtu.nse
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
description = [[
|
||||||
|
Performs simple Path MTU Discovery to the target host.
|
||||||
|
|
||||||
|
TCP or UDP packets are sent to the host with the DF (don't fragment) bit
|
||||||
|
set and with varying amounts of data. If an ICMP Fragmentation Needed
|
||||||
|
is received, or no reply is received after retransmissions, the amount
|
||||||
|
of data is lowered and another packet is sent. This continues until
|
||||||
|
(assuming no errors occur) a reply from the final host is received,
|
||||||
|
indicating the packet reached the host without being fragmented.
|
||||||
|
|
||||||
|
Not all MTUs are attempted so as to not expend too much time or network
|
||||||
|
resources. Currently the relatively short list of MTUs to try contains
|
||||||
|
the plateau values from Table 7-1 in RFC 1191, "Path MTU Discovery".
|
||||||
|
Using these values significantly cuts down the MTU search space. On top
|
||||||
|
of that, this list is rarely traversed in whole because:
|
||||||
|
* the MTU of the outgoing interface is used as a starting point, and
|
||||||
|
* we can jump down the list when an intermediate router sending a
|
||||||
|
"can't fragment" message includes its next hop MTU (as described
|
||||||
|
in RFC 1191 and required by RFC 1812)
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap --script path-mtu target
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- Host script results:
|
||||||
|
-- |_path-mtu: 1492 <= PMTU < 1500
|
||||||
|
--
|
||||||
|
-- Host script results:
|
||||||
|
-- |_path-mtu: PMTU == 1006
|
||||||
|
|
||||||
|
author = "Kris Katterjohn"
|
||||||
|
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
|
||||||
|
categories = {"safe", "discovery"}
|
||||||
|
|
||||||
|
require 'bin'
|
||||||
|
require 'packet'
|
||||||
|
|
||||||
|
local IPPROTO_ICMP = packet.IPPROTO_ICMP
|
||||||
|
local IPPROTO_TCP = packet.IPPROTO_TCP
|
||||||
|
local IPPROTO_UDP = packet.IPPROTO_UDP
|
||||||
|
|
||||||
|
-- Number of times to retransmit for no reply before dropping to
|
||||||
|
-- another MTU value
|
||||||
|
local RETRIES = 1
|
||||||
|
|
||||||
|
-- RFC 1191, Table 7-1: Plateaus. Even the massive MTU values are
|
||||||
|
-- here since we skip down the list based on the outgoing interface
|
||||||
|
-- so its no harm.
|
||||||
|
local MTUS = {
|
||||||
|
65535,
|
||||||
|
32000,
|
||||||
|
17914,
|
||||||
|
8166,
|
||||||
|
4352,
|
||||||
|
2002,
|
||||||
|
1492,
|
||||||
|
1006,
|
||||||
|
508,
|
||||||
|
296,
|
||||||
|
68
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Find the index in MTUS{} to use based on the MTU +new+. If +new+ is in
|
||||||
|
-- between values in MTUS, then insert it into the table appropriately.
|
||||||
|
local searchmtu = function(cidx, new)
|
||||||
|
if new == 0 then
|
||||||
|
return cidx
|
||||||
|
end
|
||||||
|
|
||||||
|
while cidx <= #MTUS do
|
||||||
|
if new >= MTUS[cidx] then
|
||||||
|
if new ~= MTUS[cidx] then
|
||||||
|
table.insert(MTUS, cidx, new)
|
||||||
|
end
|
||||||
|
return cidx
|
||||||
|
end
|
||||||
|
cidx = cidx + 1
|
||||||
|
end
|
||||||
|
return cidx
|
||||||
|
end
|
||||||
|
|
||||||
|
local dport = function(ip)
|
||||||
|
if ip.ip_p == IPPROTO_TCP then
|
||||||
|
return ip.tcp_dport
|
||||||
|
elseif ip.ip_p == IPPROTO_UDP then
|
||||||
|
return ip.udp_dport
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local sport = function(ip)
|
||||||
|
if ip.ip_p == IPPROTO_TCP then
|
||||||
|
return ip.tcp_sport
|
||||||
|
elseif ip.ip_p == IPPROTO_UDP then
|
||||||
|
return ip.udp_sport
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Checks how we should react to this packet
|
||||||
|
local checkpkt = function(reply, orig)
|
||||||
|
local ip = packet.Packet:new(reply, reply:len())
|
||||||
|
|
||||||
|
if ip.ip_p == IPPROTO_ICMP then
|
||||||
|
if ip.icmp_type ~= 3 then
|
||||||
|
return "recap"
|
||||||
|
end
|
||||||
|
-- Port Unreachable
|
||||||
|
if ip.icmp_code == 3 then
|
||||||
|
local is = ip.buf:sub(ip.icmp_offset + 9)
|
||||||
|
local ip2 = packet.Packet:new(is, is:len())
|
||||||
|
|
||||||
|
-- Check sent packet against ICMP payload
|
||||||
|
if ip2.ip_p ~= IPPROTO_UDP or
|
||||||
|
ip2.ip_p ~= orig.ip_p or
|
||||||
|
ip2.ip_bin_src ~= orig.ip_bin_src or
|
||||||
|
ip2.ip_bin_dst ~= orig.ip_bin_dst or
|
||||||
|
sport(ip2) ~= sport(orig) or
|
||||||
|
dport(ip2) ~= dport(orig) then
|
||||||
|
return "recap"
|
||||||
|
end
|
||||||
|
|
||||||
|
return "gotreply"
|
||||||
|
end
|
||||||
|
-- Frag needed, DF set
|
||||||
|
if ip.icmp_code == 4 then
|
||||||
|
local val = ip:u16(ip.icmp_offset + 6)
|
||||||
|
return "nextmtu", val
|
||||||
|
end
|
||||||
|
return "recap"
|
||||||
|
end
|
||||||
|
|
||||||
|
if ip.ip_p ~= orig.ip_p or
|
||||||
|
ip.ip_bin_src ~= orig.ip_bin_dst or
|
||||||
|
ip.ip_bin_dst ~= orig.ip_bin_src or
|
||||||
|
dport(ip) ~= sport(orig) or
|
||||||
|
sport(ip) ~= dport(orig) then
|
||||||
|
return "recap"
|
||||||
|
end
|
||||||
|
|
||||||
|
return "gotreply"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This is all we can use since we can get various protocols back from
|
||||||
|
-- different hosts
|
||||||
|
local callback = function(size, layer2, layer3)
|
||||||
|
local ip = packet.Packet:new(layer3, layer3:len())
|
||||||
|
return bin.pack('A', ip.ip_bin_dst)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Updates a packet's info and calculates checksum
|
||||||
|
local updatepkt = function(ip)
|
||||||
|
if ip.ip_p == IPPROTO_TCP then
|
||||||
|
ip:tcp_set_sport(math.random(0x401, 0xffff))
|
||||||
|
ip:tcp_set_seq(math.random(1, 0x7fffffff))
|
||||||
|
ip:tcp_count_checksum()
|
||||||
|
elseif ip.ip_p == IPPROTO_UDP then
|
||||||
|
ip:udp_set_sport(math.random(0x401, 0xffff))
|
||||||
|
ip:udp_set_length(ip.ip_len - ip.ip_hl * 4)
|
||||||
|
ip:udp_count_checksum()
|
||||||
|
end
|
||||||
|
ip:ip_count_checksum()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set up packet header and data to satisfy a certain MTU
|
||||||
|
local setmtu = function(pkt, mtu)
|
||||||
|
if pkt.ip_len < mtu then
|
||||||
|
pkt.buf = pkt.buf .. string.rep("\0", mtu - pkt.ip_len)
|
||||||
|
else
|
||||||
|
pkt.buf = pkt.buf:sub(1, mtu)
|
||||||
|
end
|
||||||
|
|
||||||
|
pkt:ip_set_len(mtu)
|
||||||
|
pkt.packet_length = mtu
|
||||||
|
updatepkt(pkt)
|
||||||
|
end
|
||||||
|
|
||||||
|
local basepkt = function(proto)
|
||||||
|
local ibin = bin.pack("H",
|
||||||
|
"4500 0014 0000 4000 8000 0000 0000 0000 0000 0000"
|
||||||
|
)
|
||||||
|
local tbin = bin.pack("H",
|
||||||
|
"0000 0000 0000 0000 0000 0000 6002 0c00 0000 0000 0204 05b4"
|
||||||
|
)
|
||||||
|
local ubin = bin.pack("H",
|
||||||
|
"0000 0000 0800 0000"
|
||||||
|
)
|
||||||
|
|
||||||
|
if proto == IPPROTO_TCP then
|
||||||
|
return ibin .. tbin
|
||||||
|
elseif proto == IPPROTO_UDP then
|
||||||
|
return ibin .. ubin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Creates a Packet object for the given proto and port
|
||||||
|
local genericpkt = function(host, proto, port)
|
||||||
|
local pkt = basepkt(proto)
|
||||||
|
local ip = packet.Packet:new(pkt, pkt:len())
|
||||||
|
|
||||||
|
ip:ip_set_bin_src(host.bin_ip_src)
|
||||||
|
ip:ip_set_bin_dst(host.bin_ip)
|
||||||
|
|
||||||
|
ip:set_u8(ip.ip_offset + 9, proto)
|
||||||
|
ip.ip_p = proto
|
||||||
|
|
||||||
|
ip:ip_set_len(pkt:len())
|
||||||
|
|
||||||
|
if proto == IPPROTO_TCP then
|
||||||
|
ip:tcp_parse(false)
|
||||||
|
ip:tcp_set_dport(port)
|
||||||
|
elseif proto == IPPROTO_UDP then
|
||||||
|
ip:udp_parse(false)
|
||||||
|
ip:udp_set_dport(port)
|
||||||
|
end
|
||||||
|
|
||||||
|
updatepkt(ip)
|
||||||
|
|
||||||
|
return ip
|
||||||
|
end
|
||||||
|
|
||||||
|
local ipproto = function(p)
|
||||||
|
if p == "tcp" then
|
||||||
|
return IPPROTO_TCP
|
||||||
|
elseif p == "udp" then
|
||||||
|
return IPPROTO_UDP
|
||||||
|
end
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Determines how to probe
|
||||||
|
local getprobe = function(host)
|
||||||
|
local combos = {
|
||||||
|
{ "tcp", "open" },
|
||||||
|
{ "tcp", "closed" },
|
||||||
|
-- udp/open probably only happens when Nmap sends proper
|
||||||
|
-- payloads, which doesn't happen in here
|
||||||
|
{ "udp", "closed" }
|
||||||
|
}
|
||||||
|
local proto = nil
|
||||||
|
local port = nil
|
||||||
|
|
||||||
|
for _, c in ipairs(combos) do
|
||||||
|
port = nmap.get_ports(host, nil, c[1], c[2])
|
||||||
|
if port then
|
||||||
|
proto = c[1]
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return proto, port
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sets necessary probe data in registry
|
||||||
|
local setreg = function(host, proto, port)
|
||||||
|
if not nmap.registry[host.ip] then
|
||||||
|
nmap.registry[host.ip] = {}
|
||||||
|
end
|
||||||
|
nmap.registry[host.ip]['pathmtuprobe'] = {
|
||||||
|
['proto'] = proto,
|
||||||
|
['port'] = port
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
hostrule = function(host)
|
||||||
|
if not nmap.is_privileged() then
|
||||||
|
if not nmap.registry['pathmtu'] then
|
||||||
|
nmap.registry['pathmtu'] = {}
|
||||||
|
end
|
||||||
|
if nmap.registry['pathmtu']['rootfail'] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
nmap.registry['pathmtu']['rootfail'] = true
|
||||||
|
if nmap.verbosity() > 0 then
|
||||||
|
nmap.log_write("stdout", "PATH-MTU: not running for lack of privileges")
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not (host.interface and host.interface_mtu) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local proto, port = getprobe(host)
|
||||||
|
if not (proto and port) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
setreg(host, proto, port.number)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
action = function(host)
|
||||||
|
local m, r
|
||||||
|
local gotit = false
|
||||||
|
local mtuset
|
||||||
|
local sock = nmap.new_dnet()
|
||||||
|
local pcap = nmap.new_socket()
|
||||||
|
local proto = nmap.registry[host.ip]['pathmtuprobe']['proto']
|
||||||
|
local port = nmap.registry[host.ip]['pathmtuprobe']['port']
|
||||||
|
local saddr = packet.toip(host.bin_ip_src)
|
||||||
|
local daddr = packet.toip(host.bin_ip)
|
||||||
|
local try = nmap.new_try()
|
||||||
|
local status, pkt, ip
|
||||||
|
|
||||||
|
try(sock:ip_open())
|
||||||
|
|
||||||
|
try = nmap.new_try(function() sock:ip_close() end)
|
||||||
|
|
||||||
|
pcap:pcap_open(host.interface, 104, 0, callback, "dst host " .. saddr .. " and (icmp or (" .. proto .. " and src host " .. daddr .. " and src port " .. port .. "))")
|
||||||
|
|
||||||
|
pcap:set_timeout(3000)
|
||||||
|
|
||||||
|
m = searchmtu(1, host.interface_mtu)
|
||||||
|
|
||||||
|
mtuset = MTUS[m]
|
||||||
|
|
||||||
|
local pkt = genericpkt(host, ipproto(proto), port)
|
||||||
|
|
||||||
|
while m <= #MTUS do
|
||||||
|
setmtu(pkt, MTUS[m])
|
||||||
|
|
||||||
|
r = 0
|
||||||
|
status = false
|
||||||
|
while true do
|
||||||
|
if not status then
|
||||||
|
if not sock:ip_send(pkt.buf) then
|
||||||
|
-- Got a send error, perhaps EMSGSIZE
|
||||||
|
-- when we don't know our interface's
|
||||||
|
-- MTU. Drop an MTU and keep trying.
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pcap:pcap_register(bin.pack('A', pkt.ip_bin_src))
|
||||||
|
|
||||||
|
status, _, _, ip = pcap:pcap_receive()
|
||||||
|
|
||||||
|
if status then
|
||||||
|
local t, v = checkpkt(ip, pkt)
|
||||||
|
if t == "gotreply" then
|
||||||
|
gotit = true
|
||||||
|
break
|
||||||
|
elseif t == "recap" then
|
||||||
|
elseif t == "nextmtu" then
|
||||||
|
if v == 0 then
|
||||||
|
-- Router didn't send its
|
||||||
|
-- next-hop MTU. Just drop
|
||||||
|
-- a level.
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Lua's lack of a continue statement
|
||||||
|
-- for loop control sucks, so dec m
|
||||||
|
-- here as it's inc'd below. Ugh.
|
||||||
|
m = searchmtu(m, v) - 1
|
||||||
|
mtuset = v
|
||||||
|
break
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if r >= RETRIES then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
r = r + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if gotit then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
m = m + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
pcap:close()
|
||||||
|
sock:ip_close()
|
||||||
|
|
||||||
|
if not gotit then
|
||||||
|
if nmap.debugging() > 0 then
|
||||||
|
return "Error: Unable to determine PMTU (no replies)"
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if MTUS[m] == mtuset then
|
||||||
|
return "PMTU == " .. MTUS[m]
|
||||||
|
elseif m == 1 then
|
||||||
|
return "PMTU >= " .. MTUS[m]
|
||||||
|
else
|
||||||
|
return "" .. MTUS[m] .. " <= PMTU < " .. MTUS[m - 1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -92,6 +92,7 @@ Entry { filename = "oracle-brute.nse", categories = { "auth", "intrusive", } }
|
|||||||
Entry { filename = "oracle-enum-users.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "oracle-enum-users.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "oracle-sid-brute.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "oracle-sid-brute.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "p2p-conficker.nse", categories = { "default", "safe", } }
|
Entry { filename = "p2p-conficker.nse", categories = { "default", "safe", } }
|
||||||
|
Entry { filename = "path-mtu.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "pgsql-brute.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "pgsql-brute.nse", categories = { "auth", "intrusive", } }
|
||||||
Entry { filename = "pjl-ready-message.nse", categories = { "intrusive", } }
|
Entry { filename = "pjl-ready-message.nse", categories = { "intrusive", } }
|
||||||
Entry { filename = "pop3-brute.nse", categories = { "auth", "intrusive", } }
|
Entry { filename = "pop3-brute.nse", categories = { "auth", "intrusive", } }
|
||||||
|
|||||||
@@ -480,6 +480,7 @@ Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group,
|
|||||||
if (hs->current_batch_sz == 0) /* Because later ones can have different src addy and be cut off group */
|
if (hs->current_batch_sz == 0) /* Because later ones can have different src addy and be cut off group */
|
||||||
o.decoys[o.decoyturn] = t->v4source();
|
o.decoys[o.decoyturn] = t->v4source();
|
||||||
t->setDeviceNames(rnfo.ii.devname, rnfo.ii.devfullname);
|
t->setDeviceNames(rnfo.ii.devname, rnfo.ii.devfullname);
|
||||||
|
t->setMTU(rnfo.ii.mtu);
|
||||||
// printf("Target %s %s directly connected, goes through local iface %s, which %s ethernet\n", t->NameIP(), t->directlyConnected()? "IS" : "IS NOT", t->deviceName(), (t->ifType() == devt_ethernet)? "IS" : "IS NOT");
|
// printf("Target %s %s directly connected, goes through local iface %s, which %s ethernet\n", t->NameIP(), t->directlyConnected()? "IS" : "IS NOT", t->deviceName(), (t->ifType() == devt_ethernet)? "IS" : "IS NOT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user