What is the most elegant way to use only the Raspberry Pi in the local network?
For now I blocked all outgoing ports on my router, but I don't think this is the best way to do it.
I am running NOOBS' Raspbian OS.
Raspberry Pi Stack Exchange is a question and answer site for users and developers of hardware and software for Raspberry Pi. It only takes a minute to sign up.
Sign up to join this communityWhat is the most elegant way to use only the Raspberry Pi in the local network?
For now I blocked all outgoing ports on my router, but I don't think this is the best way to do it.
I am running NOOBS' Raspbian OS.
I think that a easy way to achieve this is using the ufw (Uncomplicated Firewall), a minimalist command line tool. Actually this tool uses iptables but more friendly way. It should be installed on your system, but if not you can install it typing:
sudo apt-get install ufw
First, deny all incoming connetions to your raspberry pi:
sudo ufw default deny
Second, only allow the local network connections ( In this example I suppose that your local network is 192.168.0.0/24)
sudo ufw allow from 192.168.0.0/24
Finally, enable the ufw typing:
sudo ufw enable
You can see the active rules typing:
sudo ufw status verbose
You can learn more about UFW tool in the ubuntu documentation (https://help.ubuntu.com/community/UFW)
If you don't want ANY form of communication to the outside world, see goldilocks's answer. But if you still want to allow outgoing connections (e.g. browsing, apt-get, etc...), read on.
Your router firewall is a good setup in most cases. If you want some extra protection, you may wish to enable the Pi's own firewall. This answer applies to all linux systems, that includes your Raspberry Pi.
A Linux OS has a built-in firewall called iptables
. We will need to tell iptables to block all connections, except for connections originating from LAN.
You need to know what your LAN IP address range
is. This is achieved by writing ifconfig
in a terminal. The output varies depending on your setup, your line of interest is the inet addr
. In my case it's inet addr:10.0.0.2
.
Your LAN IP address range
is the first 3 numbers of your IP address, that is, 10.0.0.*
in my case.
Now we know what we need to do: Block all incoming traffic unless it is originating from LAN. That is, unless it's in the range 10.0.0.0 - 10.0.0.255
. Let's translate that into iptables commands:
iptables -P INPUT DROP #Block all incoming packets unless they are excluded below
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT #Allow outgoing packets
sudo iptables -A INPUT -m iprange --src-range 10.0.0.0-10.0.0.255 -j ACCEPT #Allow incoming packets if they are from LAN
sudo iptables -A INPUT -i lo -j ACCEPT # Allow localhost
sudo iptables -A OUTPUT -o lo -j ACCEPT # Allow localhost
sudo iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT #Allow incoming packets if they are part of an established connection. (Allow responses to outgoing traffic such as apt-get, browsing, time sync, etc.)
Note that this still allows the RPi to talk to the outside world if the PI itself initiated the connection. This would allow apt-get, browsing, and time syncing to function (The Pi needs the Internet to tell time)
make sure you specified your own range in case it isn't 10.0.0.*
.
That should work. But iptables forgets all commands upon reboot. Therefore, you should append the commands to a start up script. I personally do it by adding the commands above to /etc/rc.local
using sudo nano /etc/rc.local
-A
means append and -P
means prepend.
The most straightforward way would be to use the pi's own firewall (on raspbian, iptables
) to block traffic to or from any address that is not part of the LAN.
Iptables rules are assessed in order, so if you set these two first:
-A INPUT ! -s 192.168.0.0/24 -j REJECT --reject-with icmp-net-prohibited
-A OUTPUT ! -d 192.168.0.0/24 -j REJECT --reject-with icmp-net-prohibited
Then everything from outside your local subnet will be rejected, presuming this is an appropriate CIDR. If all your local addresses are prefixed 192.168.0 then it is; some routers use 192.168.1, etc. Since the 192.168 prefix is reserved for private networks in any case, you are safe using 192.168.0.0/16
, which covers all those possibilities (see also Hello World
's answer WRT determining the private network prefix from ifconfig
output; it can also begin 10.0 or 172.16).
By way of quick explanation, the !
inverts the match. This is very important, otherwise what you are doing is rejecting everything local (and by implication allowing everything else).
Raspbian by default does not activate the firewall but it is installed. A complete explanation of how it works is beyond the scope of this answer, but a very simple configuration using the aforementioned rules might look like this:
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
# The first two rules allow the system to communicate internally.
-A INPUT -i lo -j ACCEPT
-A OUTPUT -d 127.0.0.1 -j ACCEPT
# Now reject stuff from outside the LAN.
-A INPUT ! -s 192.168.0.0/16 -j REJECT --reject-with icmp-net-prohibited
-A OUTPUT ! -d 192.168.0.0/16 -j REJECT --reject-with icmp-net-prohibited
# Finally, accept everything which does not match a previous rule.
-A INPUT -j ACCEPT
-A OUTPUT -j ACCEPT
-A FORWARD -j ACCEPT
Save that as a text file owned by root with permissions 644 (or 600). It does not matter what you call it or where you put it, but for illustration I'll use /etc/iptables.rules
. To apply, run iptables-restore < /etc/iptables.rules
. There should not be any output; if there is you typed something wrong and this will be indicated. To load these at boot, add the following line to /etc/rc.local
:
/sbin/iptables-restore < /etc/iptables.rules
It's important to use the full path of executables in rc.local
(e.g. /sbin/iptables-restore
, not just iptables-restore
) since $PATH
may not be set.
You won't be able to run apt-get
, etc., this way. However, you can disable all the rules with iptables -F
, do whatever, and then reinstate them with the iptables-restore < /etc/iptables.rules
bit again.
Also, this presumes everything on your LAN is reasonably trustworthy. That's probably fine, since while what a firewall does is prevent a connection from occurring, allowing a connection to occur doesn't mean much -- e.g., it doesn't mean some malware on your iphone can now easily log in as root on the pi via ssh. It just means it won't be prevented from making a request to do so (which ssh itself will block).
Not 100% sure what is the most elegant way to only use a raspberry pi on your network. I personally have an Class C network on the 192.168.0.x range. I also gave my Raspberry Pi a static IP address. My router is locked down with all ports closed and uPnP disabled and running tests on the LAN/WAN evidently show this. I also run SPI on my Router/Firewall, Stateful Packet Inspection.
My advice would be to manually assign a static IP address, this will make life easier when you SSH and VNC into your Raspberry Pi, to do this just do the following.
1.) Turn on your Raspberry Pi (Raspbian)
2.) Login but don't start up your desktop environment.
3.) From the shell we need to view the interfaces so type this: cat /etc/network/interfaces
4.) At the line iface eth0 inet dhcp
shows our interface uses DHCP to obtain an IP address.
5.) Now we need to grab some info from our router and Pi so lets run commands ifconfig
6.) Look for
eth0 Link encap:Ethernet HWaddr b8:27:eb:b3:fc:2c
inet addr:192.168.0.10 Bcast:192.168.0.255 Mask:255.255.255.0
7.) Write down the following and take note of it
inet addr – 192.168.0.10 (Pi's Current IP Address)
Bcast – 192.168.0.255 (The Broadcast IP Range)
Mask – 255.255.255.0 (Subnet Mask Address)
8.) We need more info from the router so lets run command from the shell "netstat -nr" you can also use command "route -n" it will also display the same info. The part we are looking for is this
'Gateway' Address – 192.168.0.254
'Destination' Address – 192.168.0.0
9.) We now need to input this info into our Raspberry Pi so lets run command
sudo pico /etc/network/interfaces
You can use another editor such as nano or vi. I personally prefer Pico among others.
10.) Now lets change the following line
iface eth0 inet dhcp
and change this to iface eth0 inet static
.
11.) Also we need to include the following adjusted accordingly, choose YOUR OWN IP, I selected ".20" as my chosen static IP address
address 192.168.0.20
netmask 255.255.255.0
network 192.168.0.0
broadcast 192.168.0.255
gateway 192.168.0.254
12.) Save the file (with nano you press Ctrl+O) and update changes to the interface configuration the file you just edited.
13.) Now we can either reboot or be crafty by stopping and restarting the interface service, now lets run command
sudo /etc/init.d/networking stop
and then sudo /etc/init.d/networking start
this will stop and start the service for the interface.
14.) now lets run a ping from the command prompt to your Pi, lets do this now ping 192.168.0.20
15.) Next we could run IPTABLES
but that's going out of my depth, I'm sure someone else could shed some light into that.
Good luck, if I missed anything let me know, I hope this helps.