ip rule with tens of thousands rules in openwrt - linux

I am setting my openwrt (Netgear R3800) to support policy routing with multiple outbound interfaces by the following shell scripts. I put ip lists for different outgoing interfaces in text file and use ip rule to set different ip tables.
e.g.
ip route add default via $VPN1 dev $VPNDEV1 table 100
ip route add default via $VPN2 dev $VPNDEV2 table 200
for IPTO in `cat /root/routes/policy_ips1` ; do
ip rule add to $IPTO table 100
done
for IPTO in `cat /root/routes/policy_ips2` ; do
ip rule add to $IPTO table 200
done
The script does work most time but sometimes not stable.
As the ip lists (file policy_ips1, policy_ips2) are considerable large. like 10-20 thousands lines, each line is a subnet like '1.0.1.0/24'. I am wondering whether this is an effective way as there will be tens of thousands rules and the router will query the routing policy databas RPDB for every packet.
A further question is that as the Priority of RPDB ranges from 0 to 32767 (ref:http://man7.org/linux/man-pages/man8/ip-rule.8.html), does it mean I cannot add more than 32765 rules? Is there any capability limit in using ip rule? And is there any limit with respect to the computational capability of the router(like router's cpu, ram)?

[I'm not exactly sure this question is appropriate for SO, but]
For this kind of setup I would use Netfilter (with ipsets) to mark packets and use fwmark-based rules to match packets in the RPDB. Like
ipset create nets100 hash:net
ipset create nets200 hash:net
for IPTO in `cat /root/routes/policy_ips1` ; do
ipset add nets100 "$IPTO"
done
for IPTO in `cat /root/routes/policy_ips2` ; do
ipset add nets200 "$IPTO"
done
iptables -A PREROUTING -t mangle -m set --match-set nets100 src -j MARK --set-mark 100
iptables -A PREROUTING -t mangle -m set --match-set nets200 src -j MARK --set-mark 200
ip route add default via $VPN1 dev $VPNDEV1 table 100
ip route add default via $VPN2 dev $VPNDEV2 table 200
ip rule add fwmark 100 table 100
ip rule add fwmark 200 table 200
IPsets can easily handle lots of addresses/networks and you have a simple RPDB as a result. Although it should be noted that this adds some Netfilter overhead to packet processing, but choosing between big RPDB and ipsets I would for ipsets.
As for priority, I would read it as "no more than 32767 rules".

Related

AWS changes the port number to name

AWS automatically changes the well known port numbers to name.
For example 554 to rtsp.
When I am installing iptable rules, with the port number as 554, its getting changed to rtsp. This is creating problem when searching because my program passes 554 as parameter.
How to make sure that the AWS doesn't change the number to name ?
In the picture we can see the dpt:rtsp, which actually should be dpt:554.
Perhaps you're looking for iptables --list -n? The -n prints "numeric output of addresses and ports."

Set static IP from text file if not obtained via DHCP (sed)

When no IP address is obtained via DHCP, I want to set a static IP, which I wrote in a text file before.
Content of my staticIP.txt:
10.10.0.254
So far, I get a static IP when DHCP ist not working. I edited the /etc/dhcp/dhclient.conf for this:
timeout 10;
lease {
interface "eth0";
fixed-address 10.0.0.10;
option subnet-mask 255.255.255.0;
renew 2 2022/1/1 00:00:01;
rebind 2 2022/1/1 00:00:01;
expire 2 2022/1/1 0:00:01;
}
(Source: Set static ip if not obtained from DHCP (script))
Now I want to overwrite "fixed-address 10.0.0.10;" with the static IP "10.10.0.254" in my staticIP.txt, when no DHCP is obtained.
All I was able to do so far is replacing the "fixed-address ;" block with sed and write it to the file:
sed -i 's/fixed-address [0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}/<MANUAL ENTERED IP>/g' /etc/dhcp/dhclient.conf
Two things are missing right now:
Extracting the IP from staticIP.txt and overwrite "fixed-address [IP];"
Check if no IP was obtained via DHCP and run the sed command
I'd be glad if someone could help me.
Thanks a lot.
Why keep one IP-address in the file?
Not it be better to add it directly to a regular expression?
sed -i 's#fixed-address 10.0.0.10;#fixed-address 10.10.0.254;#' /etc/dhcp/dhclient.conf

Linux - find router IPv6 global address

I'm trying to find a way to reliably find the global IPv6 address of the local router. The command "ip -6 neigh show" doesn't display it. I have found the following works, so long as the router is using EUI-64 to generate a host address:
NET=$(ip -6 route|egrep "^[23]"|cut -d':' -f1-4)
EUI=$(ip -6 route|egrep "^default.*metric 1 "|cut -d':' -f3-6|cut -d' ' -f1)
ping6 $NET:$EUI -B -c 1 > /dev/null 2>&1
However this obviously doesn't work when EUI-64 isn't being used. Is there any other way I can find it?
There is no reliable way to determine this, as your local router doesn’t have to have a global IPv6 address at all. Best practice says it should, and the vast majority of routers out there will, but technically it’s possible that your router could only have link-local addresses on both interfaces and still route global prefixes. (Yes, I have done this before. And yes, it’s evil.)
Unless you manually added a default route pointing to a global address, you probably learned your default route via Router Advertisement which means the routing table and neighbour table (as you pointed out above) will contain a link-local address only.
However, if you perform a traceroute, the first hop is probably (key word: probably — it’s possible to spoof this stuff) your local router.
traceroute to 2600:: (2600::), 30 hops max, 80 byte packets
1 2001:db8:1::1 0.534 ms 0.510 ms 0.749 ms
2 2001:db8:2::1 32.494 ms 33.944 ms 35.406 ms
3 2600:: 36.935 ms 38.102 ms 39.860 ms
TL;DR it’s not possible to reliably determine this, so the short answer is “no”.

Understanding DNS in wireshark output

I used wireshark to collect data from some sites, and then used tcpdump to get it as a text file. For the project I'm working on, I want to count how many DNS resolutions are involved in accessing a particular website, and what the nature of the DNS responses was. The problem is I don't really understand the output from wireshark or how to interpret it to find what I'm looking for. For instance, here is a line:
21:08:05.454852 IP 10.0.0.2.57512 > ord08s09-in-f21.1e100.net.https:
Flags [.], seq 1:1419, ack 55, win 65535, options [nop,nop,TS val
1348891674 ecr 2473250009], length 1418
What do the different parts of this mean, and what will the data I'm looking for look like? I'm worried I might be using Wireshark incorrectly without knowing it.
I used wireshark to collect data from some sites, and then used tcpdump to get it as a text file.
Most people who use both tools use them for the opposite purposes. :-) I.e., they use tcpdump to capture traffic into a file and then read the file with Wireshark. If you're only using Wireshark to capture traffic, that's probably overkill - you can do the same thing with dumpcap or possibly even tcpdump.
The output you're showing is text output, so, if you "used tcpdump to get it as a text file", it's output from tcpdump, not from Wireshark; text output from Wireshark would look different. If you "used wireshark to collect data from some sites, and then used tcpdump to get it as a text file", the output from Wireshark is either a pcap file or a pcap-ng file, which is a binary file, and is completely uninterpreted raw data. The interpretation of the data in your example is being done by tcpdump, not Wireshark.
What the output is saying is:
"21:08:05.454852": the packet arrived at 21:08:05 and a fraction of a second, local time.
"IP": the packet is an IPv4 packet.
"10.0.0.2.57512 > ord08s09-in-f21.1e100.net.https": the packet is from IP address 10.0.0.2, port 57512, to the IP address whose for which the host name is "ord08s09-in-f21.1e100.net", and the port for "https", which is port 443.
See the tcpdump man page, and a description of TCP, for details on the rest of the line.
The key point here is that this is NOT DNS traffic! It's probably "HTTP-over-SSL", or "https", traffic.
In tcpdump, DNS traffic would look like
11:06:25.247272 IP 10.0.1.3.50953 > 10.0.1.1.domain: 7088+ A? www.kernel.org. (32)
11:06:25.282723 IP 10.0.1.1.domain > 10.0.1.3.50953: 7088 3/0/0 CNAME pub.us.kernel.org., A 149.20.4.69, A 198.145.20.140 (85)
or
11:06:30.622744 IP 10.0.1.3.62767 > 10.0.1.1.domain: 2439+ A? e3191.c.akamaiedge.net.0.1.cn.akamaiedge.net. (62)
11:06:30.639279 IP 10.0.1.1.domain > 10.0.1.3.62767: 2439 1/0/0 A 184.85.109.15 (78)
"A?" means that a query is being done for an A record; "CNAME" means that a CNAME record is being returned (i.e., "www.kernel.org" is an alias for "pub.us.kernel.org", and "A" means that an A record is being returned, giving an IPv4 address.
In Wireshark or TShark, it would look like:
12.316361 10.0.1.3 -> 10.0.1.1 DNS Standard query 0xc2fa A 1.courier-sandbox-push-apple.com.akadns.net
12.332894 10.0.1.1 -> 10.0.1.3 DNS Standard query response 0xc2fa A 17.149.34.59 A 17.149.34.61 A 17.149.34.62 A 17.149.34.63 A 17.149.34.57
or
15.163941 10.0.1.3 -> 10.0.1.1 DNS Standard query 0x168c A www.gnu.org
15.176266 10.0.1.1 -> 10.0.1.3 DNS Standard query response 0x168c CNAME wildebeest.gnu.org A 208.118.235.148
If you're only trying to capture DNS packet, you should use a capture filter such as "port 53" or "port domain", so that non-DNS traffic will be discarded. That filter will work with Wireshark, TShark, or tcpdump (as they use the same libpcap code for packet capture).

complex BIND zone file manipulation

I am trying to write a script that will take in a BIND zone file, grab all of the A records, in the format host ip. I've done that by grep -w 'A' "$A_ZONE"|awk '{print $1,$4}'|sort -V, to skip the IN A part. Now, I need to extract PTR records from all of the reverse zones that I have. Those are grouped by /24 subnets, so if I have a PTR record for 10.0.0.1, it would be in the 0.0.10.in-addr.arpa.zone file, as 10 IN PTR host.domain.tld. Seeing as that is a bit convoluted, I'm not sure how to extract the IP well, so that it would be in the format of the first file that I extracted, host ip.
Any suggestions?
You can use the following command:
egrep '^[0-9]+' 0.0.10.in-addr.arpa.zone | \
perl -p -e 's/^(\d+).*\s(\S+)\s*$/$2 10.0.0.$1/'
Output:
host.domain.tld. 10.0.0.10
It greps all the records that start with a number, and match the number and hostname and reverse them. The IP address is then constructed along with the hostname.
Note that in the command I showed, the subnet is hardcoded in the regexp, but you could apply similar strategy to extract it from your filename plug it into the regex.
You may also want to consider running your zone files through named-compilezone so as to make sure that they are in a canonical format suitable for scripting.

Resources