Skip to content

Commit 67b1d5a

Browse files
committed
Handle non-local source IPs better
1 parent f8f1735 commit 67b1d5a

3 files changed

Lines changed: 54 additions & 10 deletions

File tree

src/main.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -396,34 +396,46 @@ int main(int argc, char *argv[])
396396
}
397397
}
398398

399-
rawsock_eth_settings(source_mac, router_mac);
400-
rawsock_ip_settings(source_addr, ttl);
401-
402399
// Handle --source-port: auto-detection, reservation, errors
403-
if (r == 0) {
404-
const bool mandatory = banners && ip_type == IP_TYPE_TCP;
405-
const bool useful = mandatory || (banners && ip_type == IP_TYPE_UDP);
400+
const bool port_mandatory = banners && ip_type == IP_TYPE_TCP;
401+
if (r == 0 && rawsock_islocal(source_addr) == 0) {
402+
// We're using an unassigned IP, pick any random port. No need to
403+
// reserve it or care about the OS.
404+
if (port_mandatory && source_port == -1) {
405+
source_port = 25000 + rand() % 40000;
406+
log_raw("Using random source port: %d", source_port);
407+
}
408+
} else if (r == 0) {
409+
const bool port_useful = banners && ip_type == IP_TYPE_UDP;
406410
bool auto_failed = false;
407411

408-
if (mandatory || useful) {
412+
if (port_mandatory || port_useful) {
409413
int tmp = rawsock_reserve_port(source_addr, ip_type, source_port == -1 ? 0 : source_port);
410414
if (tmp >= 0) {
411-
log_debug("reserved source port: %d", tmp);
412415
source_port = tmp;
416+
if (port_mandatory)
417+
log_raw("Using reserved source port: %d", source_port);
418+
else
419+
log_debug("Using reserved source port: %d", source_port);
413420
} else {
414421
auto_failed = tmp == -1;
415422
}
416423
}
417424

418425
assert(source_port != 0);
419-
if (mandatory && source_port == -1) {
426+
if (port_mandatory && source_port == -1) {
420427
log_raw("A source port is required but was not given%s.",
421428
auto_failed ? " (automatic reservation failed)" : "");
422429
r = 1;
430+
} else if (auto_failed) {
431+
// assume the user knows what he's doing
432+
log_debug("automatic port reservation failed");
423433
}
424434
}
425435

426436
if (r == 0) {
437+
rawsock_eth_settings(source_mac, router_mac);
438+
rawsock_ip_settings(source_addr, ttl);
427439
scan_set_general(&ports, max_rate, show_closed, banners);
428440
scan_set_network(source_addr, source_port, ip_type);
429441
scan_set_output(outfile, outdef);

src/rawsock-routes.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ int rawsock_getdev(char **out_dev)
4444
if(!(d->flags & PCAP_IF_UP))
4545
continue;
4646
for(pcap_addr_t *a = d->addresses; a; a = a->next) {
47-
if(((struct sockaddr*)a->addr)->sa_family != AF_INET6)
47+
if(a->addr->sa_family != AF_INET6)
4848
continue;
4949
struct sockaddr_in6 *inaddr = (struct sockaddr_in6*) a->addr;
5050
// Exclude link-local fe80::
@@ -301,6 +301,36 @@ int rawsock_getsrcip(const struct sockaddr_in6 *dest, const char *interface, uin
301301
return ret;
302302
}
303303

304+
int rawsock_islocal(const uint8_t *ip)
305+
{
306+
char errbuf[PCAP_ERRBUF_SIZE];
307+
pcap_if_t *alldevs, *d;
308+
309+
if(pcap_findalldevs(&alldevs, errbuf) != 0) {
310+
log_debug("pcap_findalldevs: %s", errbuf);
311+
return -1;
312+
}
313+
314+
int ret = 0;
315+
for(d = alldevs; d; d = d->next) {
316+
if(!(d->flags & PCAP_IF_UP))
317+
continue;
318+
for(pcap_addr_t *a = d->addresses; a; a = a->next) {
319+
if(a->addr->sa_family != AF_INET6)
320+
continue;
321+
struct sockaddr_in6 *inaddr = (struct sockaddr_in6*) a->addr;
322+
if(!memcmp(inaddr->sin6_addr.s6_addr, ip, 16)) {
323+
ret = 1;
324+
goto found;
325+
}
326+
}
327+
}
328+
329+
found:
330+
pcap_freealldevs(alldevs);
331+
return ret;
332+
}
333+
304334
int rawsock_reserve_port(const uint8_t *addr, int type, int port)
305335
{
306336
#ifdef __linux__

src/rawsock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ int rawsock_getmac(const char *dev, uint8_t *mac); // MAC of the adapter/intf
7474
int rawsock_getgw(const char *dev, uint8_t *mac); // MAC of the default router/gateway
7575
// advice: 0=quiet, 1=default route, 2=specific IP
7676
int rawsock_getsrcip(const struct sockaddr_in6 *dest, const char *interface, uint8_t *ip, int advice);
77+
/// @return 1 if IP is local to this host, 0 if not, -1 if error
78+
int rawsock_islocal(const uint8_t *ip);
7779
/**
7880
* Reserve a local port on the specified IP for the rest of the program lifetime.
7981
* The effect should be that the kernel ignores any packets to this tuple.

0 commit comments

Comments
 (0)