Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
B1 Firewall und Proxy-Server (iptables / privoxy)
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Deutsche Dokumentation
View previous topic :: View next topic  
Author Message
pietinger
Apprentice
Apprentice


Joined: 17 Oct 2006
Posts: 240
Location: Bavaria

PostPosted: Sat May 09, 2020 8:59 pm    Post subject: B1 Firewall und Proxy-Server (iptables / privoxy) Reply with quote

(Dieser Post ist Teil einer Installation-Anleitung. Falls nicht schon geschehen lies bitte: Installation Guide for Paranoid Dummies)



B.1 Firewall und Proxy-Server (iptables / privoxy)

Die meisten nutzen eine Firewall "nur" um sich vor "Außen" zu schützen. Dies ist in jedem Fall sinnvoll und meistens auch notwendig. Ja, die heutigen (privaten) DSL-Router haben auch eine FW integriert, die meist standardmäßig bereits aktiviert ist. Dies merkt man schnell daran, wenn man sich das Log der eigenen FW ansieht und keinen einzigen DROP über Tage hinweg sieht, obwohl wir alle wissen wieviele Portscans dauernd laufen. Nur - ich traue keiner TeleKom-Huawei-Schüssel. Außerdem ist die Konfiguration für den Schutz vor dem bösen Internet noch der einfachste Part, selbst wenn man ein, zwei Ports für einen Server freischalten muss.

Die wenigsten nutzen die FW aber um sich vor dem Feind von "Innen" zu schützen - Programme die "nach Hause telefonieren" wollen. Ich werde in diesem Post für beides die nötigen Konfigurations-Schritte präsentieren. Ich fange aber mit dem Proxy-Server an. Warum ? Weil die FW danach so konfiguriert wird, dass nur der Proxy auswärtige Web-Seiten besuchen darf. Sprich, jedes Programm, das über Port 80 oder 443 versucht direkt ins Internet zu gehen, wird abgewiesen (und protokolliert). Der Proxy selbst protokolliert ebenfalls alle von ihm besuchten Seiten. Es gibt verschiedene Proxy-Server; ich nutze seit Jahren den "Privoxy" - weil er einfach ist und nur das macht was ich will: Mich ein wenig vor schlimmen Webseiten beschützen.

I. Privoxy installieren und konfigurieren
Siehe auch: https://wiki.gentoo.org/wiki/Privoxy
Code:
# emerge -pvD privoxy
# rc-update add privoxy default
# nano -w /etc/env.d/99myproxy
=>
export http_proxy="http://127.0.0.1:8118"
export https_proxy="http://127.0.0.1:8118"
<=
# env-update
# less /etc/passwd
-> notice privoxy UID for later

Leider ist privoxy in der Grundkonfiguration sehr zahm und nachsichtig. Kein Wunder ist doch die niedrigste Stufe der Filterung aktiv. Deshalb muss er noch "scharf" gemacht werden (zumindest schärfer). Dazu muss ein Teil aus der Datei /etc/privoxy/default.action (am besten per copy/paste - nicht ausschneiden) in die Datei /etc/privoxy/match-all.action übertragen werden. Wenn Du Dir mit "less" die erste Datei ansiehst und ca. zu Zeile 535 blätterst, sind dort drei Abschnitte mit folgenden Überschriften:
Code:
################
#
# Cautious settings -- safe for all sites, but offer little privacy protection
#
{ \
+change-x-forwarded-for{block} \
[...]
+set-image-blocker{blank} \
}
standard.Cautious

################
#
# Medium settings -- safe for most sites, with reasonable protection/damage tradeoff
#
{ \
+change-x-forwarded-for{block} \
[...]
+set-image-blocker{blank} \
}
standard.Medium

################
#
# Advanced settings -- reasonable privacy protection but
[...]


Wenn Du Dir nun die zweite Datei ansiehst, erkennst Du dort die Einstellungen für "Cautious settings" aus dieser 1. Datei. Aufgabe also: Kopiere mindestens die "Medium settings" und überschreibe die vorhanden settings in "match-all.action". Falls Du mich jetzt fragst, wieso das so umständlich sein muss ... Das ist es normalerweise nicht, WENN wir den "Editor" mitinstalliert hätten. Wird aber in Gentoo standardmäßig (per deaktivierten Use-flag) nicht gemacht (Vor Jahren hörte ich: Sicherheitsgründe. Stand heute ist mir nicht bekannt). Macht aber nix - ist ja nur einmalig.

Danach solltest / kannst Du das Logging noch aktivieren, welches standardmäßig auch komplett ausgeschaltet ist - und zwar in der /etc/privoxy/config. Das ist so einfach und selbsterklärend, da spare ich mir (unnötige) Erklärungen.

Fertig. Privoxy kann mit "/etc/init.d/privoxy start" sofort gestartet werden.


II. Iptables installieren und konfigurieren

Dies ist ein "klein" wenig aufwendiger. Zuerst solltest Du im Kernel ALLE FW-Module als Modul konfiguriert (und natürlich auch compiliert) haben. Gemeinerweise, kommt man erst an alle, wenn folgender Punkt gesetzt ist:
Code:
Networking support > Networking options > Network packet filtering framework (Netfilter)
[*]   Advanced netfilter configuration

Und genau von diesen "Geheimen" werden wir später mindestens diese benötigen (ziemlich weit unten auf der Seite):
Code:
Networking support > Networking options > Network packet filtering framework (Netfilter) > Core Netfilter Configuration
[M]   "owner" match support
[M]   "state" match support

Egal, Du hast einfach ALLE mit "M" eingebunden, damit du später mit "lsmod" nachsehen kannst, welche der Kernel wirklich benötigt (dann kannst Du die anderen bei der nächsten Kernel-Konfig-Orgie wieder rausschmeißen).

Wie funktioniert nun unsere Firewall. Einfach. Sehr einfach: Es ist alles verboten was nicht ausdrücklich erlaubt ist. Wenn Du keinen Server betreibst bedeutet das für den eingehen Traffic: Laß nur Pakete rein, die zu einer bereits bestehenden Verbindung gehören; aber nix was eine Neue Verbindung aufbauen will (die bestehenden Verbindungen wurden also früher von unserer Kiste nach draußen initiiert). Wie schon gesagt, der einfachste Teil.

Leider wollen wir schon auch nach draußen telefonieren. Das müssen wir alles einzeln erlauben. Aber keine Panik, so viel ist das auch nicht, da das meiste über unseren Privoxy läuft. Was brauchen wir sonst noch ? DNS, E-Mail, evtl SSH.

Noch ein Wort zum Thema "Skript welches die FW-Regeln aktiviert". Einige verteufeln dieses Vorgehen, da es (unter gewissen Umständen) absolut unsicher sein soll. Ja, aber nicht in diesem - einfachen - Fall, den ich nutze. Wenn zuerst alles gesperrt wird und danach, nach und nach einiges freigeschaltet wird, ist ein Abbruch eines Skripts (wegen z.B. Tippfehler oder fehlendem Kernel-Modul) deswegen unkritisch, weil dann halt nichts mehr freigeschaltet wird. Wenn es am Anfang in der Variablen-Definition abbricht, ändert sich die bisherige FW-Konfiguration überhaupt nicht. Ach ja, gleich noch ein Hinweis: /etc/init.d/iptables sichert selbst die FW-Konfig und lädt diese selbständig bei Booten. Das bedeutet, das Skript muß nur einmal ausgeführt werden; oder dann, wenn Du etwas änderst / ergänzt. So, jetzt gehts aber los. Zuerst wie immer ein Link:
https://wiki.gentoo.org/wiki/Iptables
Code:
# emerge -pvD iptables
# rc-update add iptables default
- gather some information for needed services; e.g. ping your E-Mail-Provider
- search for your used DNS-Server in ->
# less /etc/resolv.conf
- search for your used NTP-Server in ->
# less /etc/conv.d/ntp-client
- ping all of them to get their IP-adress
# cd /etc/MY
# nano -w fwrules-hal.sh
! copy/paste from below and edit some variables
! if your are unsure comment out some lines with #
- save and exit
# chmod 0700 fwrules-hal.sh
# ./fwrules-hal.sh
- check if there where an error, then check your new konfig with ->
# iptables -L -v -n
- dont wait until the next shutdown and save the config right now, with:
# /etc/init.d/iptables save
OPT:
# rc-update add sshd default
# lsmod
-> write down the used modules (you already know this from A.2)

Bevor Du dieses Skelett nutzt, solltest Du wenigstens mit "man iptables" die Bedeutung gewisser Parameter nachlesen ... und prüfe jede einzelne Zeile (Du benutzt sicherlich andere Server als ich). Lese auch, was der Unterschied zwischen DROP und REJECT ist ...
Code:
#!/bin/sh
#
# 2017.02.10: Initial Sript for: big
# 2017.02.11: added Server for QTWebKit
# 2017.02.15: allow out server wesnoth game
#

### Defines ###

# define general logging
logit="-j LOG --log-prefix"

# define privoxy uid from /etc/passwd
privoxy_uid="--uid-owner 104"

# change this NUMBER 104 TO YOUR UID

# define addresses
ip_gw="192.168.2.1"             # My DSL-Router
ip_dns1="a.b.c.d"               # free dns-server1: xxxxxx
ip_dns2="a.b.c.d"               # free dns-server2: xxxxxx
ip_ntp="192.53.103.108"         # time-server: ptbtime1.ptb.de
ip_hal="192.168.2.3"            # local Notebook hal
ip_guest="192.168.2.101"        # if Notebook boots with dhcp
ip_git="140.82.118.0/24"        # Servers: git (for gentoo)

### Basic Settings ###

iptables -F
iptables -X
iptables -P INPUT       DROP
iptables -P OUTPUT      DROP
iptables -P FORWARD     DROP
iptables -A INPUT       -i lo -j ACCEPT
iptables -A OUTPUT      -o lo -j ACCEPT
iptables -A INPUT       -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT      -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

### Firewall In ###

# accept some ICMP (or comment out if not desired)
iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 11 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 12 -j ACCEPT

# accept SSH IN from notebook hal without logging
iptables -A INPUT       -s ${ip_hal} -p tcp --dport 22 -j ACCEPT

# accept and log SSH from guest
iptables -A INPUT       -s ${ip_guest} -p tcp --dport 22 ${logit} "ACCEPT IN SSH GUEST "
iptables -A INPUT       -s ${ip_guest} -p tcp --dport 22 -j ACCEPT

# drop some stuff (if you have WINDOWS in your network) without logging
#iptables -A INPUT      -p udp --dport 137 -j DROP      # netbios-ns
#iptables -A INPUT      -p udp --dport 138 -j DROP      # netbios-dgm
#iptables -A INPUT      -p udp --dport 67 -j DROP
#iptables -A INPUT      -p udp --dport 68 -j DROP
iptables -A INPUT       -p 2 -j DROP                    # stuff from router

# log all other
iptables -A INPUT       ${logit} "DROP !!! "

# we dont need an extra DROP, because the standard action for INPUT is DROP (see above: "iptables -P OUTPUT DROP")


### Firewall Out ###

# accept and log GIT
iptables -A OUTPUT      -d ${ip_git} ${logit} "ACCEPT OUT GIT "
iptables -A OUTPUT      -d ${ip_git} -j ACCEPT

# accept all http / https (maybe we need sometimes http-alt) from privoxy
iptables -A OUTPUT      -p tcp --dport 80 -m owner ${privoxy_uid} -j ACCEPT
iptables -A OUTPUT      -p tcp --dport 443 -m owner ${privoxy_uid} -j ACCEPT
#iptables -A OUTPUT      -p tcp --dport 8080 -m owner {privoxy_uid} -j ACCEPT
#iptables -A OUTPUT      -p tcp --dport 8085 -m owner {privoxy_uid} -j ACCEPT

# accept dns
iptables -A OUTPUT      -d ${ip_dns1} -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT      -d ${ip_dns1} -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT      -d ${ip_dns2} -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT      -d ${ip_dns2} -p tcp --dport 53 -j ACCEPT

# Here you have to edit something
# accept mail
#iptables -A OUTPUT      -d a.b.c.d -p tcp --dport 995 -j ACCEPT  # pop3s XXXXXXX
#iptables -A OUTPUT      -d a.b.c.d/24 -p tcp --dport 587 -j ACCEPT # smtp XXXXXXXX
#iptables -A OUTPUT      -d a.b.c.d/24 -p tcp --dport 465 -j ACCEPT # ssmtp XXXXXXXXX

# accept ntp to time-server
iptables -A OUTPUT      -d ${ip_ntp} -p udp --dport 123 -j ACCEPT

# accept irc to XXXXXXX
#iptables -A OUTPUT     -d a.b.c.d  -p tcp --dport 6697 -j ACCEPT

# accept pings
iptables -A OUTPUT      -p icmp --icmp-type 8/0 -j ACCEPT

# accept server wesnoth
iptables -A OUTPUT      -d 144.76.5.6 -j ACCEPT

# accept and log server for downloading QTWebKit
iptables -A OUTPUT      -d 77.86.229.90 ${logit} "ACCEPT OUT download QTWebKit "
iptables -A OUTPUT      -d 77.86.229.90 -j ACCEPT

# accept and log ssh
iptables -A OUTPUT      -p tcp --dport 22 ${logit} "ACCEPT OUT SSH "
iptables -A OUTPUT      -p tcp --dport 22 -j ACCEPT

# accept and log hkp (pgp-key-server)
iptables -A OUTPUT      -p tcp --dport 11371 ${logit} "ACCEPT OUT HKP "
iptables -A OUTPUT      -p tcp --dport 11371 -j ACCEPT

# accept and log traceroute
iptables -A OUTPUT      -p udp --dport 33434:33524 ${logit} "ACCEPT OUT TRCR "
iptables -A OUTPUT      -p udp --dport 33434:33524 -j ACCEPT

# accept and log rsync (should be portage from gentoo only)
iptables -A OUTPUT      -p tcp --dport 873 ${logit} "ACCEPT OUT RSYNC "
iptables -A OUTPUT      -p tcp --dport 873 -j ACCEPT



# reject and log all other
iptables -A OUTPUT      ${logit} "REJECT !!! "
iptables -A OUTPUT      -j REJECT



###################################################

# for testing only !!!
# accept and log all https
# you have to comment out above reject and activate these two lines !!!
#iptables -A OUTPUT     -p tcp --dport 443 ${logit} "ACCEPT OUT HTTPS !!! "
#iptables -A OUTPUT     -p tcp --dport 443 -j ACCEPT

# for testing only !!!
# accept and log all http
# you have to comment out above reject and activate these two lines !!!
#iptables -A OUTPUT     -p tcp --dport 80 ${logit} "ACCEPT OUT HTTP !!! "
#iptables -A OUTPUT     -p tcp --dport 80 -j ACCEPT

# for testing only !!!
# accept and log all (dont use !!!)
# you have to comment out above reject and activate these two lines !!!
#iptables -A OUTPUT     ${logit} "ACCEPT OUT ALL !!! "
#iptables -A OUTPUT     -j ACCEPT

Du kannst jetzt im Kernel-Log nach "!!!" suchen um alle Drops und Rejects zu prüfen. Ebenso nach "ACCEPT" oder "ACCEPT IN" / "ACCEPT OUT". Ich empfehle Dir eh, öfter mal nach Deiner /var/log/messages zu sehen (alias: "mylog" aus A.3.3)

Zu guter letzt, solltest Du Deinem Lieblings-Browser auch noch vom neuen Proxy erzählen. Mein "Falkon" hat das sogar automatisch gemerkt und ich musste ihm gar nichts mehr mitteilen. Falls Du "wget" nutzt, könnte es auch da notwendig sein, den Proxy zu konfigurieren. Aber keine Sorge, ab jetzt siehst Du sofort, wenn jemand raus will ... aber nicht kann ...

Have Fun.


Last edited by pietinger on Sat Jun 06, 2020 3:34 pm; edited 2 times in total
Back to top
View user's profile Send private message
pietinger
Apprentice
Apprentice


Joined: 17 Oct 2006
Posts: 240
Location: Bavaria

PostPosted: Mon Jun 01, 2020 3:46 pm    Post subject: Reply with quote

Ich habe in anderen Threads manche Fragen beantwortet und dachte, ich sammle das hier mal. Vielleicht hilft es dem einen oder anderen. (Bitte lacht nicht über mein schlechtes englisch)



WHY we use a script ?

This has two reasons - one is historical. So, today it is only because of one reason.

Perhaps you already know, what you do when you type in an iptables command: You configure your kernel at runtime, like you configure your kernel at runtime with the command "sysctl". But the kernel doesnt store these settings. After a reboot they are all gone. So you have to load them again when you startup your computer. All settings you want to set with sysctl is done from the init-script: "/etc/init.d/sysctl" (you know this already).

A) A long time ago we had no script for setting the filtering settings (with iptables) at startup. Therefore you had to do it by yourself. An old example of such a script you find here: https://wiki.gentoo.org/wiki/Security_Handbook/Firewalls
Please dont use it - its outdated (I would delete it, to not confuse people reading this page) ! Today we have our own script for saving and restoring the settings: "/etc/init.d/iptables". Use only this one !

B) So, today we use a script only for one reason: If you want to change or add some rules for an existant setting. Theoretical you can use "iptables -D ..." or "-I" or -R" to delete, insert or replace some lines of your rules, but nobody does this. It is too complicated. It is easier to delete all existing rules and send all (with the new rule(s)) again to the kernel. So we use only "iptables -A" (for append) in our script. And we run the script only one time and the do an initial "/etc/init.d/iptables save". (this script must be add to the runlevel "default" also). Or a second time, if you change something ...

Stateful Inspection

I cant remember how long ago it is. Yes there was a time (I think until kernel 2.0) you had to explicitly allow an outgoing ping-request and the incoming ping-response. And the same for every protocol or target host, or target net. But then we had a (great) upcoming with a new kernel (2.2 I believe): the STATEFUL inspection ! What does this mean ?

Every communication between two computers begins with sending out the FIRST packet to the target, e.g. saying "hello, its me, I want to talk with your web-server". The answer from this web-server and all other packets related to this session, must be allowed also in the firewall, because the kernel filters EVERY packet. With the new kernel you was able to allow all RELATED packets for this session automatically. So, TODAY, when we configure a firewall, we simply allow only the INITIATING of a session (or just the first packet when using a session-less protocol like UDP) and the kernel checks by itself what is a packet belonging to this. This is why you see in every Firewall-script at minimum always these two lines:
Code:
iptables -A INPUT       -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT      -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

and today you only allow the initiating of ssh or https or even a ICMP-ping ... without explicit allowing the responses / receive packets.
And because the kernel filters really every packet - even the internal communication on loopback - you must allow this also in every case with:
Code:
iptables -A INPUT       -i lo -j ACCEPT
iptables -A OUTPUT      -o lo -j ACCEPT

And because the most packets (99%) will be filtered (=allowed) by these rules, you should put these rules to the very beginning.

Routing a packet and NAT

We have two layers with adresses: Layer 2 with its MAC adresses and layer 3 with IP adresses. Your ethernet adapter reads only incoming packets when the destination MAC adress of a packet is the MAC adress of your own ethernet adapter. All data "behind" the MAC adresses - layer 3 and layer 4 and "real" data in higher layers - are only DATA for your ethernet adapter.

But with a layer 2 adress you cannot send packets in other networks - only to MAC adresses you are LOCALLY connected. This means you must have at least ONE station which is connected to your local network AND is connected to another network: Called "Gateway" or "Router" (a router is a layer-3-gateway).

What happens when you want to browse forums.gentoo.org ?

1. Your PC doesnt know the ip adress of "forums.gentoo.org" and have to ask a DNS Server. This ip adress it gets from /etc/resolv.conf (or maybe prior to that from a dhcp request). Let it be 8.8.8.8 in this example.
2. The IP adress of this DNS Server is NOT in your own LOCAL network, so a packet to 8.8.8.8
3. must be send to a gateway/router.
4. Which one ?
5a. If you have "only" one Router in your local network, it is the DEFAULT GATEWAY.
5b. If you have two Routers - one to the internet and the other to a neighbor network - you have two ROUTES: One SPECIFIC route pointing to the neighbor network; the other route points to the internet-router as DEFAULT gateway.
(5c. If you have two router for two neighbor networks and no own direct connection to the internet, because you go into the internet over your neighbors connect, you have also (like in 5b) ONE specific route pointing to the neighbor without the internet connect and a DEFAULT route to the neighbor with the internet connect.)
(5.d If you have 3 routers, one for the internet connect and the other two for two neighbors, then you have two SEPECIFIC routes to your two neighbors and a DEFAULT route pointing to the router with the internet connect)

Summary of 5: First your Computer checks if there is a SPECIFIC route to the destination network; if not it sends ALL the rest to the default router.

6. After your Computer has desided which is the needed Router, it sends a packet to this router; BUT NOT to the IP adress of this router. It sends the packet to the MAC adress of this router. Lets say your IP adress is 192.168.1.7 and your router has 192.168.1.1, then a packet would look like =>
Code:
Layer 2: TO MAC router-if-1 FROM MAC mine [...] Layer 3: SRC IP 192.168.1.7 TARGET IP 8.8.8.8

So, you wont see the IP adress of your router in this packet.

NOW - WHAT DOES YOUR ROUTER ?

IF your router has "only" 2 interfaces (one into your local network 192.168.1.0; the other into a internet network from your provider), then your router has a default route to your provider and a specific route into your local network.

7. Again: Your router gets a packet with target IP adress 8.8.8.8 and source IP adress 192.168.1.7
8. Your router "throw away" the old MAC adresses of this packet (layer 2) and copy the rest of the date onto a NEW pair of MAC-adresses (exactly: a complete new layer-2-header) =>
Code:
Layer 2: TO MAC provider FROM MAC router-if-2 [...] Layer 3: SRC IP 192.168.1.7 TARGET IP 8.8.8.8

and sends this to the next hop in your providers network (ok, there a some more fields which must be changed also, like the checksum at the end of the packet)...

... This would be the USUALLY behavior IF ... if your ip adress would be a global IP internet adress. But you have a private IP adress:
https://en.wikipedia.org/wiki/IP_address#Private_addresses

A private IP adress is not allowed to be routed into the internet and therefore your Router must do something we call: NAT network adress translation. Now your router does not only changes the layer 2; it changes the SOURCE IP adress in layer 3 also. Your router sets its own GLOBAL IP adress as SRC adress in layer 3 and sends this new packet out to your provider - PLUS - your router keeps in mind that all answers from 8.8.8.8 should go to IP adress 192.168.1.7. This packet now looks like (a.b.c.d is a global IP internet adress of your router) =>
Code:
Layer 2: TO MAC provider FROM MAC router-if-2 [...] Layer 3: SRC IP a.b.c.d TARGET IP 8.8.8.8

This change is called SNAT (source network adress translation); the most routers do not only changes this, they change also the port number in layer-4-protocols. This is called NAPT (network address and port translation) -OR- SNAPT -OR- SNAT/PAT -OR- ... IP masquerading.
https://en.wikipedia.org/wiki/Network_address_translation

The way back:

9. Your router receives a packet from your provider with this data =>
Code:
Layer 2: TO MAC router-if-2 FROM MAC provider [...] Layer 3: SRC IP 8.8.8.8 TARGET IP a.b.c.d

10. Your router knows: This is not for me, it is for host 192.168.1.7, and therefore changes the target ip adress back to your host ip adress (PLUS again the layer 2 adresses, because it is sent out on the other (inner) interface) =>
Code:
Layer 2: TO MAC mine FROM MAC router-if-1 [...] Layer 3: SRC IP 8.8.8.8 TARGET IP 192.168.1.7


(If you now think, if there is a SNAT, then there must exist a DNAT also, then you are absolutely on the right way. DNAT is used if you have a server in your private network, which must be reached from the internet side. In an ADSL-Modem/-Router this is callled: "Port forwarding"; and it is the same as DNAT/PAT)


Back to iptables

The kernel provides two mechanism in its netfilter submodules: Filtering packets and Changing packets.

With filtering you can do FireWalling; and with "Changing" you can do NAT (... and of course you can do both, if you want).

Filtering you can do ALWAYS. On your local Computer, then its called a "Personal FireWall". On a Router, then it is a FireWall for a whole network segment.

NATing you can do only on Stations with at least two interfaces ...

... you CAN do it, when your router connects two networks with PRIVATE IP adresses, and
... you MUST DO it, if you want connect a network with PRIVATE IP adresses (directly) to the Internet.


You have a DSL-MODEM/-Router ?

Usually this Router does the NATting for you (because it must). On the private side of this router you have at least ONE PRIVATE network. Mostly 192.168.x.0; some routers allow to set another PRIVATE network ranges, like 10.0.0.0 or 172.16.0.0-172.31.0.0. "High-end-routers" allow more than ONE private network, so you can set e.g. 10.0.1.0 on eth1 of this router, and 10.0.2.0 on eth2, and 172.20.0.0 on eth3 (.. and so on). MOST SOHO - DSL-Router dont allow this. You can only set ONE private network.

What would happen if you install a "private" Router between your private network and your DSL-Router ? What will be the problem ?

Your "private" Router has two sides: The side 192.168.1.0 (to your DSL) and another side ... lets say 10.0.0.0. (of course you have enabled "forwarding" in your private router). What happens when a host with 10.0.0.7 sends a packet to 8.8.8.8 ?

Look above. These two adresses will be in layer-3 of the ip header. When your "private" router just do routing, this packet gets unchanged (on layer-3) to your DSL-Router. But your DSL-Router doesnt know anything about a network 10.0.0.0 or a host 10.0.0.7. It can do NATting only for hosts in network 192.168.1.0

So, the solution is ... you must do NATting also in your "private" router: From 10.0.0.0 to 192.168.1.0 ... with netfiler/iptables.
(Of course there is another possible way, you could do bridging your "private" router between a private network 192.168.1.0 and your DSL. Then your "router" would be only a firewall-and-bridge but not a router).


Learning iptables / example with 2 interfaces

First of all, I want to explain for what a firewall is good for. What it can do and what it cant do ?

A firewall has two sides:

1.) It can prevent you from the Internet, allowing only communications to a dedicate server you have.
2.) If you have a bad program (virus, rootkit) on your computer, it can TRY to disallow this bad program communicating with a bad server somewhere in the internet.

First look on (2). Why I wrote: "TRY" ? Because a firewall alone cant do this. Why ? The answer is: You want to go with your browser into the internet and read some webpages from "https://forums.gentoo.org". Therefore you must allow outgoing https-traffic (this is port: 443). Now you have a bad program, who wants to communicate with a bad server. This bad program communicate also over the same (open) port to its bad server ... and the firewall (must) allow this. What you would need, is a proxy server for websurfing, who log all communications into the internet for the port 443 (and 80 for normal http), so you dont go directly with your browser into the internet. Without a proxy server, the whole crap: "filtering outgoing packets" doesnt help you in any case against bad programs ... and therefore is complete senseless. Whithout a proxy you can simply allow ALL outgoing traffic and use the firewall only for (1).

In a workstation with 1 interface (e.g. ethernet) a packet can go 2 WAYS: From your computer to the net (outgoing), or from the net into your computer (ingoing).

On a router with 2 interfaces (e.g. one for LAN and one for WAN) you have 6 WAYS (with used iptables chains in brackets):
- From LAN to router (INPUT -i $LAN)
- From LAN to WAN (FORWARD -i $LAN)
- From router to LAN (OUTPUT -o $LAN)
- From router to WAN (OUTPUT -o $WAN)
- FROM WAN to router (INPUT -i $WAN)
- FROM WAN to LAN (FORWARD -i $WAN)

On a router with 3 interfaces (e.g. one for LAN, one for WAN and one for a DMZ) you have 12 WAYS (I dont want to explain now, maybe later).

Sidestep: There was a time (long long ago), a packet which should be routed, was put in first in INPUT, then in FORWARD and 3rd in OUTPUT. TODAY such a packet is put ONLY in the table "FORWARD".

So we look to a router with 2 interfaces. (In this example we do no NATting). What do you want allow and what you want disallow ? First, we make it simple and say: We have no Server inside our LAN, AND the router itself should not talk with the internet AND the LAN - just be a passive thing. Only exception: I want to go with ssh from a workstation (inside my LAN) to the router. If we set the standard action to "DROP" for all tables, what we have to allow ? I would say:

- From LAN to router (INPUT -i $LAN) => SSH (and all packets belonging to an existing session)
- From LAN to WAN (FORWARD -i $LAN) => ALL
- From router to LAN (OUTPUT -o $LAN) => only packets belonging to an existing session (should be ssh answers only)
- From router to WAN (OUTPUT -o $WAN) => ... nothing (or maybe NTP for the time in the router)
- FROM WAN to router (INPUT -i $WAN) => ... nothing (or maybe only packets belonging to an existing session (if NTP))
- FROM WAN to LAN (FORWARD -i $WAN) => only packets belonging to an existing session

We configure the kernel for our simple example (and expand it later for your wishes). What we have to do ? First we delete all existing rules (1). We have no user-definied chaines, but we want to be absolut sure there is nothing left, so (2) doesnt harm. (at this point I recommend to take a look into the manpage of iptables). Then we set a default policy to every table (3). At this point you must know some important behavior of the kernel:

1. When the kernel receives a packet, it "put it in" one of 3 tables and then compares the packet with the first rule of THIS table.
2. When this compare was successful, the kernel "jumps" to a target. We have two build-in targets: DROP and ACCEPT. These targets are "end-station"-targets. The kernel doesnt proof any other rules after this. Another target is "LOG". This is NOT an end-station. The kernel just log something and proceed with the next rule.
4. When this compare was not successful, the kernel does nothing and proceed with the next rule.
3. If there is/was no "end-station-rule" for the specific packet, the kernel does what the default policy say.

Side-Note: Because of 1. it makes no difference if you define first all the rules for INPUT and then for OUTPUT or reverse. For performance reasons it is only important to think about the order of the rules WITHIN one table.

Next we think about which ways (of which protocols) would induce the most traffic ? This we set at first for performance reasons. We allow all traffic from LAN to WAN (4) and allow all packets "answering back" (5). Now we have two of our 6 lines allowed. The next is our ssh from LAN into the router (6) and back (7). Al last ( 8 ) we have to allow the internal communication of the loopback interface of the router (this you have to do always for every firewall-type, so it is usually at the beginning of every script you will find). Now we are finished.

Dont forget: (5) and (7) you define only one time. If you want allow, for example, additional "http" from LAN into the router, you need only allow this unidirectional, because "the way back" is handled from (7) again.
Code:
#!/bin/sh

# Defines

# please edit this with your real interface-names you will find with "ifconfig" (your names maybe begins with "enp....")
LAN=eth0
WAN=eth1

### (1)
iptables -F

### (2)
iptables -X

### (3)
iptables -P INPUT       DROP
iptables -P OUTPUT      DROP
iptables -P FORWARD     DROP

### (4)
iptables -A FORWARD     -i $LAN -j ACCEPT

### (5)
iptables -A FORWARD     -i $WAN -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

### (6)
iptables -A INPUT       -i $LAN -p tcp --dport 22 -j ACCEPT

### (7)
iptables -A OUTPUT      -o $LAN -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

### (8)
iptables -A INPUT       -i lo -j ACCEPT
iptables -A OUTPUT      -o lo -j ACCEPT


Now we make one change: We allow our ntp-daemon in our router to communicate with a time-server from the internet. You have 3 options to do that:

a) You allow your router ONLY NTP-traffic out to ALL Servers in the internet, or
b) You allow your router ALL traffic out to ONE Time-Server in the internet, or
c) You allow your router ONLY NTP-traffic out to ONE Time-Server.

I must not say which is the most secure option (c), but if we trust our ntp-client AND we have more than ONE time-server we want to ask for the time, it is practically to allow (a) because this will be one rule and (c) would be a rule for every time-server we want to connect. I give you (c) as example (you could simply add to the script, but wait a little bit):
Code:
NTPSERVER="a.b.c.d"

iptables -A OUTPUT      -o $WAN -d $NTPSERVER -p udp --dport 123 -j ACCEPT
iptables -A INPUT       -i $WAN -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

You should be able now to change this, if you want solution (a) ... =>
Code:
iptables -A OUTPUT      -o $WAN -p udp --dport 123 -j ACCEPT
iptables -A INPUT       -i $WAN -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

In this two examples we did something which is not absolutely necessary: Differentiate between LAN and WAN in the "conntrack lines". Usually you have only 3 lines at the beginning of your script and then only your special allows. So, our next example has an other sequence.

Now we want to log something. You have 4 options for what you want to log:

a) Every connection from X to Y, or
b) One specific action, or
c) Some specific actions (but not too much), or
d) Almost every connection, except some specific actions

We can shorten this list, because for (b) and (c) we do the same. First we want to log every ssh-connection to our router. You see, the matching is identically, only the target is LOG instead of ACCEPT =>
Code:
#!/bin/sh
LAN=eth0
WAN=eth1
iptables -F
iptables -X
iptables -P INPUT       DROP
iptables -P OUTPUT      DROP
iptables -P FORWARD     DROP
iptables -A INPUT       -i lo -j ACCEPT
iptables -A OUTPUT      -o lo -j ACCEPT
iptables -A INPUT       -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT      -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD     -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -A FORWARD     -i $LAN -j ACCEPT

### this is the line we need AND it MUST be BEFORE the "end-station-accept":
iptables -A INPUT       -i $LAN -p tcp --dport 22 -j LOG --log-prefix "ssh-connect from my LAN "

iptables -A INPUT       -i $LAN -p tcp --dport 22 -j ACCEPT

Now you want to log all connections going outside to the internet (e.g. only for troubleshooting):
Code:
#!/bin/sh
LAN=eth0
WAN=eth1
iptables -F
iptables -X
iptables -P INPUT       DROP
iptables -P OUTPUT      DROP
iptables -P FORWARD     DROP
iptables -A INPUT       -i lo -j ACCEPT
iptables -A OUTPUT      -o lo -j ACCEPT
iptables -A INPUT       -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT      -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD     -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT       -i $LAN -p tcp --dport 22 -j LOG --log-prefix "ssh-connect from my LAN "
iptables -A INPUT       -i $LAN -p tcp --dport 22 -j ACCEPT

### this is the line we need AND it MUST be BEFORE the "end-station-accept":
iptables -A FORWARD     -i $LAN -j LOG --log-prefix "connect from my LAN to internet "
iptables -A FORWARD     -i $LAN -j ACCEPT

At last, the most difficult: You want to log every connection, except all http and https (web-surfing). This is a little bit trickier, because you have to allow first all, you dont want to log; then log all the rest, and then allowing all the rest =>
Code:
#!/bin/sh
LAN=eth0
WAN=eth1
iptables -F
iptables -X
iptables -P INPUT       DROP
iptables -P OUTPUT      DROP
iptables -P FORWARD     DROP
iptables -A INPUT       -i lo -j ACCEPT
iptables -A OUTPUT      -o lo -j ACCEPT
iptables -A INPUT       -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT      -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD     -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT       -i $LAN -p tcp --dport 22 -j LOG --log-prefix "ssh-connect from my LAN "
iptables -A INPUT       -i $LAN -p tcp --dport 22 -j ACCEPT

# Allow all outgoing http and https without logging:
iptables -A FORWARD     -i $LAN -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD     -i $LAN -p tcp --dport 443 -j ACCEPT

# Now we log the rest (with the same line from above)
iptables -A FORWARD     -i $LAN -j LOG --log-prefix "connect from my LAN to internet "

# and allow the rest (with the same line from above)
iptables -A FORWARD     -i $LAN -j ACCEPT


I recommend to work with "iptables -L -v -n" in combination with "iptables -Z" because you can see the count of packets for every rule (-Z set it to zero).

User-defined Chains

For which constellations you should use one or more user-defined chains ?

If you are a programmer, you know what is a subroutine or function. And you also know when it is worthwhile to use a subroutine. A chain is something similar to a subroutine. You use it if you want define the same rules for more than one "way" in your firewall. If you have a personal firewall (one interface), I can hardly find a reason to use a user-defined chain. At least you need two interfaces in your host. And even then it matters what you want allow or disallow for every way a data-packet could go. If you want your host acting as a passive firewall, you maybe didnt find enough rules which will be used doubled. Because you need 4 Rules (doubled 8 ) to skimp 1 line. I explain:

You need one line for creating your user-defined chain with "iptables -N MYCHAIN",
PLUS 2 lines for jumping in it,
PLUS 4 lines you want to define.
= 7 lines

If you have 2 interfaces, but allow all outgoing traffic and filtering only incoming traffic (e.g. from the internet), it is also hard to find doubled rules. And even if you filters your outgoing traffic from your LAN-side to the internet, but dont allow your router outgoing traffic, its hard to find doubled rules. So in my example we allow our workstations in our LAN AND our router some outgoing traffic: DNS, NTP, Ping, traceroute and ssh. Without a user-defined chain you would need 10 lines. With a user-defined chain we need 8 lines:
Code:
iptables -N MY

# we allow some outgoing protocols in our user-defined chain named MY

# DNS
iptables -A MY      -p udp --dport 53 -j ACCEPT
# NTP
iptables -A MY      -p udp --dport 123 -j ACCEPT
# pings
iptables -A MY      -p icmp --icmp-type 8/0 -j ACCEPT
# traceroute
iptables -A MY      -p udp --dport 33434:33524 -j ACCEPT
# ssh
iptables -A MY      -p tcp --dport 22 -j ACCEPT

# now we jump from our 2 ways we want to allow (accept) in our MY chain

# first we allow our router to do DNS, NTP, Ping, traceroute and ssh
iptables -A OUTPUT  -o $WAN -j MY

# then we allow all hosts in our LAN the same
iptables -A FORWARD  -i $LAN -j MY

(This example is not complete; its only for demonstration purposes)

If you ask me now, what if I want allow my hosts in my LAN a little bit MORE than my router. What I have to do then ?

The same as always: You allow it only for the way you want. (additionly/beside your chain)
Code:
# Allow all outgoing http and https without logging:
iptables -A FORWARD     -i $LAN -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD     -i $LAN -p tcp --dport 443 -j ACCEPT


Before or after the jump to my CHAIN ?

You CAN set these rules before OR after your jump to your chain, but you SHOULD set the rules in dependence which rule will be asked more often. For example: You have massive web-browsing, then you should allow outgoing https-traffic BEFORE you jump into your chains (in reallity the performance difference in private installations is soooo little, it rather doesnt much matters).

Must I define the rules in my user chain before I jump in it ?

YES !

What does netfilter when no rule in my chain was selected ?

Netfilter goes back, where it came from (there is an invisible "return") and matches the rules in the next lines ... and at the end it does the DEFAULT action if not even one rule matched.

If you want to learn more about this, take a look in this thread:
https://forums.gentoo.org/viewtopic-t-1114432.html
Back to top
View user's profile Send private message
pietinger
Apprentice
Apprentice


Joined: 17 Oct 2006
Posts: 240
Location: Bavaria

PostPosted: Sat Jun 06, 2020 11:03 am    Post subject: Hole punching Reply with quote

Hole punching

See also: https://en.wikipedia.org/wiki/Hole_punching_(networking)

Can my FireWall protect me against this ?

It depends. First of all you must know which "holes" in your firewall are secure. If you allow outgoing traffic to a SPECIFIC server AND a specific port (e.g. -d $NTP -p ...), this hole cant be used from a "bad" programm, because it could connect only to this server, and usually this time-server wants to talk only about times ... ;-)

Not as secure as above, but nearly, is a hole when you allow a connection to a SPECIFIC server - like the servers of my bank. If you trust these servers (and be to lazy for defining specific ports) this cause no problem.

A real problem is allowing a protocol to ALL servers of the internet. A bad programm can use this kind of holes to communicate with a bad server (listening to all ports). If you allow traceroute with
Code:
iptables -A OUTPUT      -p udp --dport 33434:33524 -j ACCEPT

a bad programm can missuse these open ports and connect to a bad server. What can you do against this ?

1.) Not allowing it, or
2.) Logging it, and doing a daily (automated) check of your logs. Yes, this DOESNT protect you against hole punching, but you see it after it happened. I must say it clear: Sometimes a firewall cant protect you, it only can warn you, there was "something" ...

Conclusion: If you allow some protocols without specific destination hosts, then you should LOG this ALWAYS (like I do in the example of my first post).

Have Fun, and please report any issues in this thread.

If you have questions, be free and ask here also.
Back to top
View user's profile Send private message
pietinger
Apprentice
Apprentice


Joined: 17 Oct 2006
Posts: 240
Location: Bavaria

PostPosted: Fri Jun 19, 2020 12:43 pm    Post subject: Reply with quote

Hole punching II

I forgot to mention another possibility to avoid problems with an open hole in your firewall:

3.) Allow a protocol only before you need it and then close it immediately afterwards. This is a rare use case where you need the parameters "-I" and "-D" of your iptables command, like in this "mysync.sh"-script (I really use):
Code:
#!/bin/sh
iptables -I OUTPUT 3 -p tcp --dport 873 -j LOG --log-prefix "ACCEPT OUT RSYNC "
iptables -I OUTPUT 4 -p tcp --dport 873 -j ACCEPT
emerge --sync
iptables -D OUTPUT 4
iptables -D OUTPUT 3

(I selected line number 3, because rule nr. 1 is allowing loopack packets and line nr. 2 allows packets from established sessions.)


User-defined Chains II

A friend has to serve some other workstations via ssh (via internet connections). Instead of allowing all ssh out, he wanted allow only ssh to the specific clients of his customers (see: hole punching). This is now a rare case where you can work with a user-defined chain in a personal firewall to shorten the number of rules the kernel has to proof. Look to this excerpt from his rules:
Code:
[...]
iptables -N ALL-SSH
iptables -A ALL-SSH -d a.b.c.d  # client xxxxxxxxxxxxxx
[...]
iptables -A ALL-SSH -d a.b.c.d  # client xxxxxxxxxxxxxx
iptables -A ALL-SSH -j LOG --log-prefix "REJ SSH "
iptables -A ALL-SSH -j REJECT
[...]
# the next line is rule nr. 5 of his outgoing rules (optimized on the basis of his traffic)
iptables -A OUTPUT  -p tcp --dport 22 -j ALL-SSH
[...]
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) Deutsche Dokumentation All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum