自己动手打造路由器
在网上看到一篇文章
The Ars guide to building a Linux router from scratch
很有意思,不仅过程很有趣,还能学到不少东西(文章封面就是作者的路由器照片)。这里简单总结记录一下。
打造路由器整个过程,分硬件和软件两部分。
硬件就是买一台mini PC,然后作者还加了个SSD硬盘。
软件部分需要懂得我们平常买的路由器里具体包含哪些功能,除了UI以外,有
Routing
NAT
DHCP
DNS
很神奇的是,上面这些功能只需要在一个普通的linux系统上就能配置和实现,作者用的ubuntu。
首先,作者的mini PC上有2个网口,一个LAN口,和一个WAN口,网线插到WAN口上。
先手动配置这2个网口,编辑文件 /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# The loopback network interface
auto lo
iface lo inet loopback
# The WAN interface, marked Lan1 on the case
auto p4p1
iface p4p1 inet dhcp
# The LAN interface, marked Lan2 on the case
auto p1p1
iface p1p1 inet static
address 192.168.99.1
netmask 255.255.255.0
可以看到这里p4p1是WAN口,p1p1是LAN口。
路由
配置路由,就是配置IP packet转发,非常简单,编辑文件 /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
# Uncomment the next line to enable packet forwarding for IPv6
# Enabling this option disables Stateless Address Autoconfiguration
# based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
如上,设置 net.ipv4.ip_forward=1 即可。
创建 iptables 规则文件
为了方便管理,作者建了一个 iptables 规则文件 /etc/network/if-pre-up.d/iptables ,之后对 iptables的修改都在这个文件里,每次修改完,只需要执行 /etc/network/if-pre-up.d/iptables 即可生效,注意设立需要设置该文件的访问权限为755,root可以可读可写可执行,其他用户可读可执行。如下:
#!/bin/sh
/sbin/iptables-restore < /etc/network/iptables
可以看到它执行了 /etc/network/iptables 里的内容,如下:
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Service rules
-A INPUT -j DROP
# Forwarding rules
-A FORWARD -j DROP
COMMIT
这个文件里有2种 iptable 规则,一个是nat,一个是filter。后续看到具体的用途。注意,这里filter规则里,所有的input和forward请求都会drop,所以我们的路由规则实际上是非常严格的,后面会按照需求逐渐放开权限。
NAT
nat其实就在nat规则链里添加一条命令的事。
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# p4p1 is WAN interface, #p1p1 is LAN interface
-A POSTROUTING -o p4p1 -j MASQUERADE
COMMIT
所有去到WAN口的packet都执行masquerade。
DHCP 和 DNS
因为实在太简单,这连个步骤合成一个。
安装dhcp和dns对应的软件。
sudo apt-get install isc-dhcp-server
sudo apt-get install bind9
编辑文件 /etc/dhcp/dhcpd.conf:
subnet 192.168.99.0 netmask 255.255.255.0 {
range 192.168.99.100 192.168.99.199;
option routers 192.168.99.1;
option domain-name-servers 192.168.99.1;
option broadcast-address 192.168.99.255;
}
很简单,就不解释了。
这里虽然安装好了,但是还不够,需要配置iptables规则。允许局域网里的其他节点访问我们的路由器。因为目前为止,我们的路由器仅仅自己可以访问公网,但它不能接收局域网的请求,也不会转发数据包。
# Service rules
# basic global accept rules - ICMP, loopback, traceroute, established all accepted
-A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -m state --state ESTABLISHED -j ACCEPT
# enable traceroute rejections to get sent out
-A INPUT -p udp -m udp --dport 33434:33523 -j REJECT --reject-with icmp-port-unreachable
# DNS - accept from LAN
-A INPUT -i p1p1 -p tcp --dport 53 -j ACCEPT
-A INPUT -i p1p1 -p udp --dport 53 -j ACCEPT
# SSH - accept from LAN
-A INPUT -i p1p1 -p tcp --dport 22 -j ACCEPT
# DHCP client requests - accept from LAN
-A INPUT -i p1p1 -p udp --dport 67:68 -j ACCEPT
# drop all other inbound traffic
-A INPUT -j DROP
访问外网
这是一个基本功能,需要2条规则。一个是conntrack,一个是把LAN
口的请求都转发到WAN口上。
# Forwarding rules
# forward packets along established/related connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# forward from LAN (p1p1) to WAN (p4p1)
-A FORWARD -i p1p1 -o p4p1 -j ACCEPT
# drop all other forwarded traffic
-A FORWARD -j DROP
到这一步,一个基本路由器的功能都实现了。
端口转发
实现端口转发的目的是可以让公网直接连局域网的服务器,一般用户实际上没有这个需求。在普通的路由器里可以通过UI设置,但在我们自己打造的路由器,每一条转发规则,需要在路由表里修改两项。
nat规则:
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# p4p1 is WAN interface, #p1p1 is LAN interface
-A POSTROUTING -o p4p1 -j MASQUERADE
# NAT pinhole: HTTP from WAN to LAN
-A PREROUTING -p tcp -m tcp -i p4p1 --dport 80 -j DNAT --to-destination 192.168.99.100:80
COMMIT
filter规则:
# Forwarding rules
# forward packets along established/related connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# forward from LAN (p1p1) to WAN (p4p1)
-A FORWARD -i p1p1 -o p4p1 -j ACCEPT
# allow traffic from our NAT pinhole
-A FORWARD -p tcp -d 192.168.99.100 --dport 80 -j ACCEPT
# drop all other forwarded traffic
-A FORWARD -j DROP
最终,完整的 iptables 规则文件 /etc/network/iptables:
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# p4p1 is WAN interface, #p1p1 is LAN interface
-A POSTROUTING -o p4p1 -j MASQUERADE
# NAT pinhole: HTTP from WAN to LAN
-A PREROUTING -p tcp -m tcp -i p4p1 --dport 80 -j DNAT --to-destination 192.168.99.100:80
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# Service rules
# basic global accept rules - ICMP, loopback, traceroute, established all accepted
-A INPUT -s 127.0.0.0/8 -d 127.0.0.0/8 -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -m state --state ESTABLISHED -j ACCEPT
# enable traceroute rejections to get sent out
-A INPUT -p udp -m udp --dport 33434:33523 -j REJECT --reject-with icmp-port-unreachable
# DNS - accept from LAN
-A INPUT -i p1p1 -p tcp --dport 53 -j ACCEPT
-A INPUT -i p1p1 -p udp --dport 53 -j ACCEPT
# SSH - accept from LAN
-A INPUT -i p1p1 -p tcp --dport 22 -j ACCEPT
# DHCP client requests - accept from LAN
-A INPUT -i p1p1 -p udp --dport 67:68 -j ACCEPT
# drop all other inbound traffic
-A INPUT -j DROP
# Forwarding rules
# forward packets along established/related connections
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# forward from LAN (p1p1) to WAN (p4p1)
-A FORWARD -i p1p1 -o p4p1 -j ACCEPT
# allow traffic from our NAT pinhole
-A FORWARD -p tcp -d 192.168.99.100 --dport 80 -j ACCEPT
# drop all other forwarded traffic
-A FORWARD -j DROP
COMMIT
最后,作者还做了一些性能测试,我不太关注,就不记录了。
Refer:
https://arstechnica.com/gadgets/2016/04/the-ars-guide-to-building-a-linux-router-from-scratch/
Comments