Routing
m (→Basic) |
|||
(21 intermediate revisions by one user not shown) | |||
Line 5: | Line 5: | ||
# show the routing table, with numeric addresses | # show the routing table, with numeric addresses | ||
route -n | route -n | ||
− | # add a default route, through eth0 | + | # add a default route, through eth0, via 192.168.1.1 |
− | route add default dev eth0 | + | route add default dev eth0 gw 192.168.1.1 |
# add a route to 10.150.0.0/24 through eth0 | # add a route to 10.150.0.0/24 through eth0 | ||
route add -net 10.150.0.0/24 dev eth0 | route add -net 10.150.0.0/24 dev eth0 | ||
Line 16: | Line 16: | ||
The most unhelpful error possible. It generally means you have done something silly... check: | The most unhelpful error possible. It generally means you have done something silly... check: | ||
* Your addresses - e.g. is the gateway you specified actually directly accessible through the interface? | * Your addresses - e.g. is the gateway you specified actually directly accessible through the interface? | ||
+ | |||
+ | =The Linux `iptables` command= | ||
+ | <source lang="bash"> | ||
+ | # list the current rules (not very useful without -v) | ||
+ | iptables -vL | ||
+ | |||
+ | # list the current rules in the NAT table | ||
+ | iptables -t nat -vL | ||
+ | </source> | ||
+ | |||
+ | ==NAT== | ||
+ | ===Setup=== | ||
+ | To setup NAT between interfaces eth0 (outside) and tun0 (inside - e.g. a [[OpenVPN|VPN]] server) | ||
+ | <source lang="bash"> | ||
+ | INSIDE=tun0 | ||
+ | OUTSIDE=eth0 | ||
+ | echo 1 > /proc/sys/net/ipv4/ip_forward | ||
+ | iptables -t nat -A POSTROUTING -o ${OUTSIDE} -j MASQUERADE | ||
+ | iptables -A FORWARD -i ${OUTSIDE} -o ${INSIDE} -m state --state RELATED,ESTABLISHED -j ACCEPT | ||
+ | iptables -A FORWARD -i ${INSIDE} -o ${OUTSIDE} -j ACCEPT | ||
+ | </source> | ||
+ | |||
+ | ===Port Forwarding=== | ||
+ | <source lang="bash"> | ||
+ | EXTERNAL_PORT=230 | ||
+ | INTERNAL_HOST=192.168.0.4 | ||
+ | INTERNAL_PORT=23 | ||
+ | iptables -t nat -A PREROUTING -i ${OUTSIDE} -p tcp --dport ${EXTERNAL_PORT} -j DNAT --to ${INTERNAL_HOST}:${INTERNAL_PORT} | ||
+ | </source> | ||
+ | |||
+ | ===Port Forwarding 2=== | ||
+ | This is possibly an unexpected use of port forwarding. | ||
+ | Here, we are inside a restrictive network that permits internet-bound traffic on port 80, but not 22. | ||
+ | The network's internet-side IP is <code>${EXT_IP}</code> | ||
+ | <source lang="bash"> | ||
+ | iptables -t nat -A PREROUTING -p tcp --dport 80 -s ${EXT_IP} -j REDIRECT --to-port 22 | ||
+ | </source> | ||
+ | After running this, we can connect to our SSH server using port 80. | ||
+ | Any attempt to access the web server from this network will fail, but others will be blissfully unaware! | ||
+ | |||
+ | ==='Proxying'=== | ||
+ | This will allow access to ${SOME_HOST} on ${SOME_PORT} via your server, ${MY_HOST} on ${MY_PORT} | ||
+ | <source lang="bash"> | ||
+ | iptables -t nat -A PREROUTING -p tcp -d ${SOME_HOST} --dport ${SOME_PORT} -j DNAT --to-destination ${MY_HOST}:${MY_PORT} | ||
+ | iptables -t nat -A POSTROUTING -p tcp -j MASQUERADE | ||
+ | </source> | ||
+ | |||
+ | ==='Proxying' 2=== | ||
+ | Again, '''this is untested''', but should allow access to ${SOME_HOST} when in fact you were trying to talk to ${REAL_HOST} | ||
+ | <source lang="bash"> | ||
+ | iptables -t nat -A PREROUTING -d ${REAL_HOST} -j DNAT --to-destination ${SOME_HOST} | ||
+ | iptables -t nat -A POSTROUTING -s ${SOME_HOST} -j SNAT --to-source ${REAL_HOST} | ||
+ | </source> | ||
+ | |||
+ | ===Teardown=== | ||
+ | <source lang="bash"> | ||
+ | # remove the first item in the 'FORWARD' table, twice - you added two (forward & reverse) | ||
+ | iptables -D FORWARD 1 | ||
+ | iptables -D FORWARD 1 | ||
+ | iptables -t nat -D POSTROUTING 1 | ||
+ | </source> | ||
+ | |||
+ | ===Prevent Linux from responding to its other addresses=== | ||
+ | When you have a Linux machine setup with two interfaces, it's possible to communicate with it, from either interface, using either address, even if <code>ip_forward</code> is set to <code>0</code>. | ||
+ | This is because Linux uses a [http://en.wikipedia.org/wiki/Host_model Weak Host Model]. | ||
+ | To prevent this, behavior you have to specifically tell the system to drop messages that are received unless they are sent to the suitable address. | ||
+ | |||
+ | Here's an example that will configure the system like a home 'router', with port 22 (SSH) forwarded to 192.168.1.1 | ||
+ | <source lang="bash"> | ||
+ | INSIDE=eth0 | ||
+ | INSIDE_IP=192.168.1.1 | ||
+ | INSIDE_NET=192.168.1.0 | ||
+ | INSIDE_MASK=24 | ||
+ | |||
+ | OUTSIDE=eth1 | ||
+ | OUTSIDE_IP=100.64.0.1 | ||
+ | OUTSIDE_NET=100.64.0.0 | ||
+ | OUTSIDE_MASK=24 | ||
+ | </source> | ||
+ | <source lang="bash"> | ||
+ | # flush any existing rules | ||
+ | iptables -F | ||
+ | iptables -t nat -F | ||
+ | |||
+ | # setup some reasonable defaults | ||
+ | iptables -P INPUT DROP | ||
+ | iptables -P FORWARD DROP | ||
+ | iptables -P OUTPUT ACCEPT | ||
+ | |||
+ | # setup the interfaces | ||
+ | ifconfig ${OUTSIDE} up ${OUTSIDE_IP}/${OUTSIDE_MASK} | ||
+ | ifconfig ${INSIDE} up ${INSIDE_IP}/${INSIDE_MASK} | ||
+ | |||
+ | # enable forwarding | ||
+ | echo 1 > /proc/sys/net/ipv4/ip_forward | ||
+ | |||
+ | # setup NATing | ||
+ | iptables -t nat -A POSTROUTING -o ${OUTSIDE} -j MASQUERADE | ||
+ | iptables -A FORWARD -i ${OUTSIDE} -o ${INSIDE} -m state --state RELATED,ESTABLISHED -j ACCEPT | ||
+ | iptables -A FORWARD -i ${INSIDE} -o ${OUTSIDE} -j ACCEPT | ||
+ | |||
+ | # allow the internal people to get out | ||
+ | iptables -I INPUT -i ${INSIDE} -s ${INSIDE_NET}/${INSIDE_MASK} -j ACCEPT | ||
+ | |||
+ | # allow the external people to get to US ONLY | ||
+ | iptables -I INPUT -i ${OUTSIDE} -d ${OUTSIDE_IP} -j ACCEPT | ||
+ | </source> | ||
+ | |||
+ | ====Basic==== | ||
+ | Alternatively, if you're just after the ability to prevent this cross-interface communication, then use this (yes, you could invert the DROP/ACCEPT to achieve the same result) | ||
+ | <source lang="bash"> | ||
+ | ifconfig eth0 up 192.168.0.1/24 | ||
+ | iptables -I INPUT -i eth0 ! -d 192.168.0.0/24 -j DROP | ||
+ | |||
+ | ifconfig eth1 up 192.168.1.1/24 | ||
+ | iptables -I INPUT -i eth1 ! -d 192.168.1.0/24 -j DROP | ||
+ | </source> | ||
+ | |||
+ | ====Also...==== | ||
+ | Look at rp_filter (Reverse Path Filter) | ||
+ | [http://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.kernel.rpf.html] |
Latest revision as of 17:05, 16 December 2015
Contents |
[edit] The Linux `route` command
Below is a list of useful commands
# show the routing table, with numeric addresses route -n # add a default route, through eth0, via 192.168.1.1 route add default dev eth0 gw 192.168.1.1 # add a route to 10.150.0.0/24 through eth0 route add -net 10.150.0.0/24 dev eth0 # add a route to 10.150.0.0/24 through eth0, and the gateway 192.168.0.15 route add -net 10.150.0.0/24 gw 192.168.0.15 dev eth0
[edit] SIOCADDRT: No such process
The most unhelpful error possible. It generally means you have done something silly... check:
- Your addresses - e.g. is the gateway you specified actually directly accessible through the interface?
[edit] The Linux `iptables` command
# list the current rules (not very useful without -v) iptables -vL # list the current rules in the NAT table iptables -t nat -vL
[edit] NAT
[edit] Setup
To setup NAT between interfaces eth0 (outside) and tun0 (inside - e.g. a VPN server)
INSIDE=tun0 OUTSIDE=eth0 echo 1 > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -o ${OUTSIDE} -j MASQUERADE iptables -A FORWARD -i ${OUTSIDE} -o ${INSIDE} -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i ${INSIDE} -o ${OUTSIDE} -j ACCEPT
[edit] Port Forwarding
EXTERNAL_PORT=230 INTERNAL_HOST=192.168.0.4 INTERNAL_PORT=23 iptables -t nat -A PREROUTING -i ${OUTSIDE} -p tcp --dport ${EXTERNAL_PORT} -j DNAT --to ${INTERNAL_HOST}:${INTERNAL_PORT}
[edit] Port Forwarding 2
This is possibly an unexpected use of port forwarding.
Here, we are inside a restrictive network that permits internet-bound traffic on port 80, but not 22.
The network's internet-side IP is ${EXT_IP}
iptables -t nat -A PREROUTING -p tcp --dport 80 -s ${EXT_IP} -j REDIRECT --to-port 22
After running this, we can connect to our SSH server using port 80. Any attempt to access the web server from this network will fail, but others will be blissfully unaware!
[edit] 'Proxying'
This will allow access to ${SOME_HOST} on ${SOME_PORT} via your server, ${MY_HOST} on ${MY_PORT}
iptables -t nat -A PREROUTING -p tcp -d ${SOME_HOST} --dport ${SOME_PORT} -j DNAT --to-destination ${MY_HOST}:${MY_PORT} iptables -t nat -A POSTROUTING -p tcp -j MASQUERADE
[edit] 'Proxying' 2
Again, this is untested, but should allow access to ${SOME_HOST} when in fact you were trying to talk to ${REAL_HOST}
iptables -t nat -A PREROUTING -d ${REAL_HOST} -j DNAT --to-destination ${SOME_HOST} iptables -t nat -A POSTROUTING -s ${SOME_HOST} -j SNAT --to-source ${REAL_HOST}
[edit] Teardown
# remove the first item in the 'FORWARD' table, twice - you added two (forward & reverse) iptables -D FORWARD 1 iptables -D FORWARD 1 iptables -t nat -D POSTROUTING 1
[edit] Prevent Linux from responding to its other addresses
When you have a Linux machine setup with two interfaces, it's possible to communicate with it, from either interface, using either address, even if ip_forward
is set to 0
.
This is because Linux uses a Weak Host Model.
To prevent this, behavior you have to specifically tell the system to drop messages that are received unless they are sent to the suitable address.
Here's an example that will configure the system like a home 'router', with port 22 (SSH) forwarded to 192.168.1.1
INSIDE=eth0 INSIDE_IP=192.168.1.1 INSIDE_NET=192.168.1.0 INSIDE_MASK=24 OUTSIDE=eth1 OUTSIDE_IP=100.64.0.1 OUTSIDE_NET=100.64.0.0 OUTSIDE_MASK=24
# flush any existing rules iptables -F iptables -t nat -F # setup some reasonable defaults iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # setup the interfaces ifconfig ${OUTSIDE} up ${OUTSIDE_IP}/${OUTSIDE_MASK} ifconfig ${INSIDE} up ${INSIDE_IP}/${INSIDE_MASK} # enable forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # setup NATing iptables -t nat -A POSTROUTING -o ${OUTSIDE} -j MASQUERADE iptables -A FORWARD -i ${OUTSIDE} -o ${INSIDE} -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A FORWARD -i ${INSIDE} -o ${OUTSIDE} -j ACCEPT # allow the internal people to get out iptables -I INPUT -i ${INSIDE} -s ${INSIDE_NET}/${INSIDE_MASK} -j ACCEPT # allow the external people to get to US ONLY iptables -I INPUT -i ${OUTSIDE} -d ${OUTSIDE_IP} -j ACCEPT
[edit] Basic
Alternatively, if you're just after the ability to prevent this cross-interface communication, then use this (yes, you could invert the DROP/ACCEPT to achieve the same result)
ifconfig eth0 up 192.168.0.1/24 iptables -I INPUT -i eth0 ! -d 192.168.0.0/24 -j DROP ifconfig eth1 up 192.168.1.1/24 iptables -I INPUT -i eth1 ! -d 192.168.1.0/24 -j DROP
[edit] Also...
Look at rp_filter (Reverse Path Filter) [1]