The test environment is:
2 Operating Systems ubuntu server 10.04 installed on VirtualBox
iptables v1.4.4
ip_conntrack module loaded
these are my test rules:
$IPTABLES -A INPUT -p TCP -m state --state NEW -j LOG --log-prefix "[-IPT-]NEW:"
$IPTABLES -A INPUT -p TCP -m state --state ESTABLISHED -j LOG --log-prefix "[-IPT-]ESTABLISHED:"
$IPTABLES -A INPUT -p TCP -m state --state RELATED -j LOG --log-prefix "[-IPT-]RELATED:"
$IPTABLES -A INPUT -p TCP -m state --state INVALID -j LOG --log-prefix "[-IPT-]INVALID:"
using
hping3 -c 1 192.168.0.1 -p 80 [flags combination]
I get:
no flag INVALID
syn NEW
ack NEW
rst INVALID
fin INVALID
syn ack INVALID
syn rst INVALID
syn fin INVALID
ack rst INVALID
ack fin INVALID
rst fin INVALID
syn ack rst INVALID
syn rst fin INVALID
ack rst fin INVALID
syn ack rst fin INVALID
I've read more tutorials that say the first packet seen by netfilter has to be NEW(in the user land). I don't understand if there is something in my computer that doesn't work.
Then, on the internet, there are a lot of rules that filter considering both connection state and tcp flags. Are all these wrong? The reason is quite simple: if they are dropping packets that matches new and ! --syn, the result is painful...a lot of packets pass through the "firewall"(if it can be named so)
Is it possible that newer versions of iptables have a different behavior?
please, can you confirm me if you are getting the same result on yours computers?
thx, I'll appreciate!
Looking at your results, they're pretty much how I would have expected. Some of the decisions have been taken based on the conntrack module, others I believe based on allowed behaviour (i.e. flag combinations) in TCP RFC.
When there are no flags, that is completely invalid as per the RFC.
I believe that you know the reasonSYN is categorised as NEW and that's very much as expected :)
ACK is categorised as new because the conntrack module (afaik) doesn't begin tracking a connection until the third step of the 3-way handshake.
Both RST and FIN are only valid as part of a live, currenty TCP connection so this rejection is based on the conntrack module tracking the connection here.
When you combine the TCP flags, as a "new" packet, in some cases (e.g. the ere should be a previous connection) whereas in others they are all just plainly invalid combinations (again) as per the RFC. For example, a TCP segment should never have the RST and FIN flags set, for ACK and RST to be set there should be a current TCP connection already set up in order for something to be torn down ( again as you alluded to the conntrack module is tracking the connection here).
Have you tried running the same test on Ubuntu 12.04 or RHEL? I will see if I can try later but I believe your computer is working as expected. Nice test though :)
Then, on the internet, there are a lot of rules that filter considering both connection state and tcp flags. Are all these wrong?
I don't believe so, I think everyone's use case is different and by combining both, people are generally being cautious. However, most folk don't do as much testing as you have (kudos) nor do all have the understanding.
Is it possible that newer versions of iptables have a different behavior?
No, not as far as I'm aware.
Related
My site now is under ddos-attack,
"ss -ant" shows a lot of FIN-WAIT-2 (and some FIN-WAIT-1) connections from one ip (and random ports), about 500-700 connections:
FIN-WAIT-2 0 0 ::ffff:MY_IP:443 ::ffff:ATTACKERS_IP:RANDOM_PORT
.... 500-700 times
Im trying to use
iptables -A INPUT -s ATTACKERS_IP -j DROP
and
iptables -A INPUT -p tcp -m tcp --tcp-flags FIN,RST RST -m limit --limit 1/s -j ACCEPT
and
echo "2" > /proc/sys/net/ipv4/tcp_fin_timeout
but it doesnt help - new connections are coming in with another random ports.
So, how to TOTALLY block specific IP by iptables (or maybe something else) to prevent FIN-WAIT-2 flood by ip which freezes the server?
It depends, there's a ton of ways to approach the problem. You could block the whole country if it's a foreign-language country (provided your website is not of international market or interest).
or
You could block an entire ip block
or
You could use cloudflare to pre-mitigate the problem
or
You could ....
I have 2 kinds of proxies in my local machine : stunnel and TOR-VPN.
stunnel is listening on port 6666
TOR-VPN is listening on port 9040
I want to get web traffic to go to stunnel first and the output traffic of stunnel go to tor-vpn. This needs double redirecting. is it possible to do it with iptables? I mean by using "table nat chain OUTPUT".
Because as far as I know "table nat chain OUTPUT" cant be called twice.
web traffic = browser listening on 127.0.0.1:6666
these are my rules:
iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 6666
iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner bob -m tcp -j
REDIRECT --to-ports 9040
iptables -t nat -A OUTPUT -p udp -m owner --uid-owner bob -m udp
--dport 53 -j REDIRECT --to-ports 53
iptables -t filter -A OUTPUT -p tcp --dport 6666 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp -m owner --uid-owner bob -m tcp
--dport 9040 -j ACCEPT
iptables -t filter -A OUTPUT -p udp -m owner --uid-owner bob -m udp
--dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -m owner --uid-owner bob -j DROP
the above rules make stunnel work independently from TOR/VPN.
i mean when browser is set with proxy, no traffic will go through TOR/VPN but if i turn off the proxy in browser, all traffic will go through TOR/VPN.
now i want to let browser have the proxy on and all web traffic go to stunnel first, but outgoing stunnel traffic(outgoing loopback traffic) redirects to TOR/VPN(127.0.0.1:9040)
is it possible ? how can i do that? somehow i mean double redirecting inside system.
Policy of all tables is ACCEPT
Checking that this is what you mean :
You have stunnel bound to port 6666 (localhost:6666) and you have tor bound to 9040 (localhost:9040). You want it so your web traffic will go THROUGH stunnel (so destination is localhost:6666) but the OUTBOUND traffic FROM stunnel (with inbound traffic originally from your client redirected to stunnel) should be DESTINED to tor (localhost:9040) ? Is this correct ?
If so, and I am thinking clearly enough (it is just 7:00 and I've been awake far too many hours for a difficult night), this is indeed possible (the reverse is, too). You need to masquerade the destination address (and indeed port) based on the source (address and port (you don't have to specify both, I might add)). Something like this:
iptables -t nat -I PREROUTING -p tcp --sport 6666 -j DNAT --to-destination 9040
If this is not what you mean (or alternatively I made a typo, am not clear headed or being an idiot in some way (in all cases showing myself to be a user as everyone is!), if any it is probably the latter) then please respond. I'll see about enabling email notification so that I see the response. If I don't, however, I apologise in advance.
As an aside: unless you have a final rule in each CHAIN (not table, just as an fyi: a table is filter, nat (which I specify in the above and indeed it is necessary), etc. and CHAIN is INPUT, OUTPUT, FORWARD and others created by the option -N) you shouldn't have -P ACCEPT ('that which is not explicitly permitted is forbidden' and similar wording - i.e. have DROP). The exception is perhaps OUTPUT (but depends on what you need, in the end). However, when dealing with interface 'lo' you'll want to ACCEPT all traffic always, in any case (i.e. specify -i lo and -o lo, depending on chain, and jump to ACCEPT). Of course, maybe you're behind another device but still best practise to not accept anything and everything! (I should also state that you have different chains per table so yes you can specify different tables but the policy is for the chain IN that table)
Edit: something else: no, you don't have to deal with SNAT when you want DNAT and the reverse is true. Anything to the contrary is a misunderstanding. The reason is you're masquerading the CONNECTION. As the man page shows:
It specifies that the destination address of the
packet should be modified (and all future packets in this connection will also be mangled), and rules should cease being examined.
Edit:
If I understand you (now) you actually have two interfaces involved. Or more specifically you need the following:
You have a service you want encrypted. This is tor. Now, you're using stunnel to do this. To this end you want stunnel to forward traffic to tor. Is this right? If yes, then know that stunnel has the following directives (I actually use similar for something else). Here's a mock setup of a service.
[tor]
accept = 6666
connect = 9040
In addition, just as a note: connect can also be a remote address (remote address implies an external address (with port) or even a certain interface (by IP and also with port) on the system (I use external in the sense of you specify ip and port rather than just a port). Furthermore, accept can specify address (with same rules: ip before the port (except that it is obviously on the local machine so no external IP)). You could explain it, perhaps, as stunnel is where the service would bind to except that the service is stunnel and the service it is encrypting is elsewhere (shortly: the bind(2) call allows specific IP or all IPs on the system, and you're basically configuring stunnel to do this).
(And yes, you're right: the sport should have been dport.)
IF this is not what you need then I do not understand all variables. In that case, if you can elaborate on which interfaces (this includes ports and which service per interface) are involved as well as clients involved (and where they send). Because it is a lot more helpful if others know EXACTLY what you need than infer certain parts. Makes it much easier to solve a problem if you know what the problem is entirely. Maybe I've been dense and I should put together it all (and I admit sleep problems - which I have for a long, long time - does not help that, but...) I haven't, I think.
I found the answer by myself. in my first post, i said something that was completely wrong and because of that, i could not do double redirecting.
i said:
Because as far as I know "table nat chain OUTPUT" cant be called twice
it is wrong and "table nat chain OUTPUT" can be called twice. i dont know what exactly i did 2 months ago that thought "table nat chain OUTPUT" cant be called twice.
this is the tables and chains order when using some services on loopback interface or not:
Without having any services on loopback:
Generated packets on local machine -> nat(OUTPUT) -> filter(OUTPUT) -> wlan(ethernet) interface
With having some services on loopback:
Generated packets on local machine -> nat(OUTPUT) -> filter(OUTPUT) -> loopback interface -> nat(OUTPUT) -> filter(OUTPUT) -> wlan(ethernet) interface
these are my rules to solve the problem:
iptables -t nat -A OUTPUT -p tcp -m tcp --dport 6666 -j REDIRECT --to-ports 6666
iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner bob -m tcp -j REDIRECT --to-ports 9040
iptables -t nat -A OUTPUT -p udp -m owner --uid-owner bob -m udp --dport 53 -j REDIRECT --to-ports 53
iptables -t nat -A OUTPUT -d "StunnelServerIp" -o wlan0 -p tcp -j REDIRECT --to-ports 9040
iptables -t filter -A OUTPUT -p tcp -m owner --uid-owner bob -m tcp --dport 9040 -j ACCEPT
iptables -t filter -A OUTPUT -p udp -m owner --uid-owner bob -m udp --dport 53 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp -m tcp --dport 6666 -j ACCEPT
iptables -t filter -A OUTPUT -m owner --uid-owner bob -j DROP
We have a number of iptables rules for forwarding connections, which are solid and work well.
For example, port 80 forwards to port 8080 on the same machine (the webserver). When a given webserver is restarting, we forward requests to another IP on port 8080 which displays a Maintenance Page. In most cases, this other IP is on a separate server.
This all worked perfectly until we installed bridge-utils and changed to using a bridge br0 instead of eth0 as the interface.
The reason we have converted to using a bridge interface is to gain access to the MAC SNAT/DNAT capabilities of ebtables. We have no other reason to add a bridge interface on the servers, as they don't actually bridge connections over multiple interfaces.
I know this is a strange reason to add a bridge on the servers, but we are using the MAC SNAT/DNAT capabilities in a new project and ebtables seemed to be the safest, fastest and easiest way to go since we are already so familiar with iptables.
The problem is, since converting to a br0 interface, iptables PREROUTING forwarding to external servers is no longer working.
Internal PREROUTING forwarding works fine (eg: request comes in on port 80, it forwards to port 8080).
The OUTPUT chain also works (eg: we can connect outwards from the box via a local destination IP:8080, and the OUTPUT chain maps it to the Maintenance Server IP on a different server, port 8080, and returns a webpage).
However, any traffic coming into the box seems to die after the PREROUTING rule if the destination IP is external.
Here is an example of our setup:
Old Setup:
iptables -t nat -A PREROUTING -p tcp --dport 9080 -j DNAT --to-destination $MAINTIP:8080
iptables -a FORWARD --in-interface eth0 -j ACCEPT
iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
New Setup: (old setup in various formats tried as well..., trying to log eth0 and br0 packets)
iptables -t nat -A PREROUTING -p tcp --dport 9080 -j DNAT --to-destination $MAINTIP:8080
iptables -a FORWARD --in-interface br0 -j ACCEPT
iptables -t nat -A POSTROUTING --out-interface br0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
Before changing to br0, the client request would go to server A at port 9080, and then be MASQUERADED off to a different server $MAINTIP.
As explained above, this works fine if $MAINTIP is on the same machine, but if it's on another server, the packet is never sent to $MAINTIP under the new br0 setup.
We want the packets to go out the same interface they came in on, MASQUERADED, as they did before we switched to using a single-NIC bridge (br0/bridge-utils).
I've tried adding logging at all stages in iptables. For some reason the iptables TRACE target doesn't work on this setup, so I can't get a TRACE log, but the packet shows up in the PREROUTING table, but seem to be silently dropped after that.
I've gone through this excellent document and have a better understanding of the flow between iptables and ebtables:
http://ebtables.sourceforge.net/br_fw_ia/br_fw_ia.html
From my understanding, it seems that the bridge is not forwarding the packets out the same interface they came in, and is dropping them. If we had a second interface added, I imagine it would be forwarding them out on that interface (the other side of the bridge) - which is the way bridges are meant to work ;-)
Is it possible to make this work the way we want it to, and PREROUTE/FORWARD those packets out over the same interface they came in on like we used to?
I'm hoping there are some ebtables rules which can work in conjunction with the iptables PREROUTING/FORWARD/POSTROUTING rules to make iptables forwarding work the way it usually does, and to send the routed packets out br0 (eth0) instead of dropping them.
Comments, flames, any and all advice welcome!
Best Regards,
Neale
I guess you did, but just to be sure, did you add eth0 to the bridge?
Although, I am not sure what the problem is, I will give some debugging tips which might assist you or other when debugging bridge/ebtables/iptables issues:
Make sure that "/proc/sys/net/bridge/bridge-nf-call-iptables" is enabled (1)
This cause bridge traffic to go through netfilter iptables code.
Note that this could affect performance.
Check for packet interception by the ebtabels/iptables rules,
Use the commands:
iptables -t nat -L -n -v
ebtables -t nat -L –Lc
This might help you to understand if traffic is matched and intercepted or not.
Check that IP NAT traffic appears in the conntrack table:
conntrack –L (if installed)
Or
cat /proc/net/nf_conntrack
Check MAC learning of the bridge
brctl showmacs br0
Use tcpdump on the eth0 and on br0 to check if packets seen at both as expected
Use the –e option to see MAC address as well.
For debugging, try to put the bridge interface in promiscuous mode, maybe the bridge receives packets with different MAC address (in promiscuous mode it will accept different MAC as well)
Maybe set bridge forward delay to 0
brctl setfd br0 0
And disable stp (spanning tree protocol)
brctl stp br0 off
What is your routing table looks like?
Try adding specific or default route rule with "dev br0"
I hope it helps a bit…
Good luck
Well only 1.5 years old but could be useful for later lookups. Looking at your link just now, it says specifically there brouting will ignore the packet, if MAC is on same side of bridge (and not another port or the bridge itself (see fig 2.b in your link).
Adding to that, I simply quote from this link: http://wiki.squid-cache.org/ConfigExamples/Intercept/LinuxBridge
"... ebtables DROP vs iptables DROP
In iptables which in most cases is being used to filter network traffic the DROP target means "packet disappear".
In ebtables a "-j redirect --redirect-target DROP" means "packet be gone from the bridge into the upper layers of the kernel such as routing\forwarding" (<-- relevant bit!)
Since the ebtables works in the link layer of the connection in order to intercept the connection we must "redirect" the traffic to the level which iptables will be able to intercept\tproxy.
ANd therein is your answer (bet added for future visitors of course, unless you are still at it ,p)
I'd like to make SSH-identification a little stronger using iptables extensions (or IPSec tools?) for marking (while sending) and matching (while recieving) the packets between my laptop and my server.
I need no VPN, just to send additional information in IP Options header (or in the AH field?).. while talking to server.
It would be nice if it could be possible by using iptables plugins for Debian only (to first alter the headers and then compare the key inside on my remote host).
I googled for a day and found such topics as Inspect protocols AH and ESP for content; Using iptables string-matching filter; Payload mangling etc - but for a now I could not understand the most important thing: which packet to install for Debian on both computers:)
My dream is to block connections using iptables on port 22 (which have no signature inside) before the SSH handshake starts. Can you help me, please?
I did my homework again, and gurus online told me to use the ToS field, "which remains the same while being transmitted over global networks".
An example how to set it:
iptables -t mangle -A PREROUTING -p TCP --dport 22 -j TOS --set-tos 0x10
And it's a very small field (256 bits), filled up with the service information, so there is no much room to play with and you must be very careful. But still!..
Later then the ToS value can be read on the receiving machine using something like
iptables -A INPUT -p tcp -m tos --tos 0x16
I am trying to block web bots that open up numerous connections within a short period of time. I am using this syntax:
-A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
-A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 1 --hitcount 20 -j logdropconnection
My problem is that I can't relax these parameters without iptables throwing an error. When I try to increase the hitcount beyond 20, I get an error. Shouldn't I be able to set that to anything I want? For example, limit my connections to 100/second?
Since you failed to mention the error in your question, I'll take a wild guess that dmesg shows this error:
xt_recent: hitcount (100) is larger than packets to be remembered (20)
This is a setting of the xt_recent (sometimes referred to as ipt_recent) kernel module.
You can increase the limit by updating (or creating) /etc/modprobe.d/options.conf with:
options xt_recent ip_pkt_list_tot=100
Note: this could be a problem to implement on VPS hosts with kernel-sharing features.