Skip to content

Commit 0a4c2b3

Browse files
committed
Handle non-local source IPs better
1 parent f8f1735 commit 0a4c2b3

4 files changed

Lines changed: 59 additions & 14 deletions

File tree

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ Building fi6s is fairly easy on any recent Linux system, e.g. on Ubuntu:
1616

1717
The scanner executable will be ready at `./fi6s`.
1818

19-
Note that fi6s is developed and tested solely on Linux. It *should* work on other
20-
UNIX-like platforms, but don't expect it to run on Windows.
19+
Note that fi6s is developed and tested solely on Linux. Other UNIX-like platforms
20+
*should* work, but not Windows.
2121

2222
## Usage
2323

@@ -66,7 +66,7 @@ It would typically send RST frames in this case.
6666
By default fi6s will ask the OS to reserve an ephemeral port and use it for the
6767
duration of the scan. This only works on Linux.
6868

69-
If this doesn't work or you are on a different platform you will have to use a static
69+
*If this doesn't work* or you are on a different platform you will have to set a
7070
source port and configure your firewall to drop traffic on this port, e.g.:
7171

7272
# ip6tables -A INPUT -p tcp -m tcp --dport 12345 -j DROP
@@ -102,4 +102,5 @@ This means fi6s may not perform as expected or outright not work if:
102102
* your network has consistent packet loss
103103

104104
For banner collection note that fi6s does not come with anything resembling a real TCP
105-
stack. It merely supports sending one query and reading response data that follows. Resends are not implemented.
105+
stack. It merely supports sending one query and reading response data that follows.
106+
Resends or window logic are not implemented.

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)