歡迎您光臨本站 註冊首頁

透明防火牆架設的完全攻略(bridge+iptables+squid)

←手機掃碼閱讀     火星人 @ 2014-03-29 , reply:0

架設透明代理和防火牆是linux平台上很熱的話題,在水木上也有相關文章,但完全的攻略在公網上也很少,最近架了一台,前後花去一個多星期(我這人手腳慢,別笑,中間笑話也頗多)覺得還是把過程寫下來的好,可以讓人依葫蘆畫瓢。

先把網路環境說一下,一個200人左右的區域網,一個C class,一台路由器做NAT(一個公網ip)。網路環境還是很簡單的,目的就是在路由器和區域網間加一台透明防火牆進去,同時完成cache server的功能。我不想讓防火牆做nat,一是因為已經有了一台路由器,要物盡其用。二是 nat其實也是很耗資源的事(尤其當下面的clients特別多時,對router cpu的要求還是很高的,我就碰到過一台cisco 75XX 路由器拖1000個用戶5分鐘死一次機的事,後來不得已架了一台PIX做NAT)還是分分開的好。三是萬一cache server 趴下了,只要把鏈路重新旁接一下,網路照樣用(頂多性能不好),不會影響用戶。

防火牆的平台為一P4 2.4G server, 512M內存,2×80GHD,兩塊NIC。安裝的是RH8.0 kernel 2.4.20(原來想裝gentoo的,但要命的1.4到現在才剛到RC3,等不及了,偷了一把懶~_~)

先下載bridge做橋接,bridge的作用就是讓兩塊網卡變成一個橋設備,讓兩端的網路埠完全透明地轉發packets,而讓 iptables起到blocking的作用。下載地址為http://bridge.sourceforge.net(什麼?sourceforge?不知道上不去啊!沒辦法,因為眾所周知的原因,大夥找https proxy繞上去吧!)需下載bridge-utils-0.9.6.tar.gz和 bridge-nf-0.0.7-against-2.4.19.diff。(這個很重要,否則iptables無法攔截轉發過來的packets)

再到http://netfilter.samba.org下載iptables,併到www.linuxhq.xom下載最新的kernel及patch。

在/usr/src下釋放kernel,進入/usr/src/linux,並把bridge的patch打上,patch ?p1 < bridge-nf-0.0.7-against-2.4.19.diff.

最後還有個問題,此時用ifconfig看到的流量,在過了4G之後就會被置0,然後從頭開始,很不爽。這是因為 'RX bytes' and 'TX bytes'等變數的數據類型為 unsigned long,即2^32,到了4G就重置,其實把它們改成 unsigned long long(2^64)就可以了。更改

/usr/src/linux/include/linux/netdevice.h 和../linux/net/core/dev.c,以下是打patch時的記錄,找到文件改掉相應代碼即可。

diff -urN linux-orig/include/linux/netdevice.h linux/include/linux/netdevice.h

--- linux-orig/include/linux/netdevice.h

+++ linux/include/linux/netdevice.h

@@ -96,10 +96,10 @@

struct net_device_stats

{

- unsigned long rx_packets; /* total packets received */

- unsigned long tx_packets; /* total packets transmitted */

- unsigned long rx_bytes; /* total bytes received */

- unsigned long tx_bytes; /* total bytes transmitted */

+ unsigned long long rx_packets; /* total packets received */

+ unsigned long long tx_packets; /* total packets transmitted */

+ unsigned long long rx_bytes; /* total bytes received */

+ unsigned long long tx_bytes; /* total bytes transmitted */

unsigned long rx_errors; /* bad packets received */

unsigned long tx_errors; /* packet transmit problems */

unsigned long rx_dropped; /* no space in linux buffers */

diff -urN linux-orig/net/core/dev.c linux/net/core/dev.c

--- linux-orig/net/core/dev.c

+++ linux/net/core/dev.c

@@ -1689,7 +1689,7 @@

int size;

if (stats)

- size = sprintf(buffer, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu %8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu
",

+ size = sprintf(buffer, "%6s:%8llu %7llu %4lu %4lu %4lu %5lu %10lu %9lu %8llu %7llu %4lu %4lu %4lu %5lu %7lu %10lu
",

dev->name,

stats->rx_bytes,

stats->rx_packets, stats->rx_errors,

這樣編譯后,ifconfig的4G重置問題就被消除了。

下面就是重新編譯kernel了,make menuconfig.....

注意,除了要把該編譯進去的驅動編進去(象NIC什麼的,我第一次編時就漏了一塊網卡,汗ing)還要把最重要的iptables給enable 起來,進入Network Options,選中Network Packet filtering (replaces ipchains),這樣就會打開IP: Netfilter Configuration --> 子菜單,進入,選中裡面所有的選項,然後回到 Network Options菜單,選中「802.1d Ethernet Bridging」 和 「netfilter (firewalling) support」兩個選項(一看就知道很重要。)

退出,開編。

make dep

make modules

make modules_install

make bzImage

完成後cp /usr/src/linux/arch/i386/bzImage /boot/bzImage.bridge

然後把System.map拷至/boot下再在lilo或grub中更改相應配置即可(這就不細說了,重編kernel的文章到處都有。)

重起,如果正常,開始下一步,tar ?xzvf bridge-utils-0.9.6.tar.gz.

cd ./bridge-utils-0.9.3

make

make install(編譯bridge並安裝,具體的安裝目錄可在make文件生成時指定。)

完畢后可以先試試bridge的基本命令。如brctl addbr mybridge (創建bridge mybridge,然後用ifconfig查看會發現多了一個mybridge埠)

brctl addif mybridge eth0

brctl addif mybridge eth1 (把eth0和eth1包含到mybridge中)

然後需要對各埠做以下動作

ifconfig eth0 0.0.0.0 promisc

ifconfig eth1 0.0.0.0 promisc(打開混雜模式)

這時橋接即已成功,從router和區域網轉發過來的消息開始通過機器,這時你會發覺滿屏的tcp/ip轉發消息讓你無法下手,硬碟也狂轉,這是 syslogd和klogd做的怪,log的priviledge設得太低,改掉它。telnet 進入機器(這時你只能telnet,console上已經泛濫成災。)kill 掉syslogd和klogd,在/etc/syslog.conf中屏蔽掉*.info至 /var/log/messages的rules(一開始我不知道這個,結果第一天下午連到網路上去,第二天上午一看,/var/log下的 messages居然有2.7G,My God),並修改/etc/init.d/syslog,在daemon klogd 一項后加上-2 -c 4 (提高klogd的消息轉發級別),重起syslogd,哈哈,整個世界清凈了!!!

其實我們也可以寫個啟動腳本放在/etc/init.d中,如下:

#!/bin/bash

. /etc/init.d/functions

return=$rc_done

start() {

echo "Starting service bridge tranfw"

brctl addbr tranfw || return=$rc_failed

brctl addif tranfw eth0 || return=$rc_failed

brctl addif tranfw eth1 || return=$rc_failed

ifconfig eth0 0.0.0.0 promisc || return=$rc_failed

ifconfig eth1 0.0.0.0 promisc || return=$rc_failed

brctl sethello tranfw 1 || return=$rc_failed

brctl setmaxage tranfw 4 || return=$rc_failed

brctl setfd tranfw 4 || return=$rc_failed

ifconfig tranfw 192.168.9.11 broadcast 192.168.9.255 promisc up || return=$rc_failed

/sbin/route add default gw 192.168.9.1 netmask 0.0.0.0 metric 1

echo -e "$return"

}

stop() {

echo "Shutting down service bridge tranfw"

brctl delif tranfw eth0 || return=$rc_failed

brctl delif tranfw eth1 || return=$rc_failed

brctl delbr tranfw || return=$rc_failed

echo -e "$return"

}

status(){

ifconfig tranfw

brctl show tranfw

}

restart(){

$0 stop && $0 start || return=$rc_failed

}

case "$1" in

start)

start

;;

stop)

stop

;;

restart)

restart

;;

status)

status tranfw

RETVAL=$?

;;

*)

echo $"Usage: $0 {start|stop|status|restart}"

RETVAL=1

esac

exit $RETVAL

這樣啟動時就自己起來了。

下一步,我們可以開始配iptables了

tar ?xjvf iptables-1.2.7.tar.bz2

cd ./iptables-1.2.7

make

make install

安裝很簡單。關鍵是如何用,我懶,抄了個腳本就開用了,如下:

#!/bin/bash

#Flush all rules from the chains

iptables -F

#Delete all user created chains (mainly KEEP_STATE chain)

iptables -X

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

##Create special chain KEEP_STATE

iptables -N KEEP_STATE

iptables -F KEEP_STATE

##Drop bad states

iptables -A KEEP_STATE -m state --state INVALID -j DROP

iptables -A KEEP_STATE -m state --state RELATED,ESTABLISHED -j ACCEPT

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

#Drop RST/ACKs to limit OS detection through pinging

iptables -A FORWARD -p tcp --tcp-flags RST RST,ACK -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "RST/ACK: "

iptables -A FORWARD -p tcp --tcp-flags RST RST,ACK -j DROP

#Deny pings from outside

iptables -A FORWARD -p icmp --icmp-type 0/0 -d 192.168.9.0/24 -j ACCEPT

iptables -A FORWARD -p icmp --icmp-type 0/0 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Drop Echo Reply: "

iptables -A FORWARD -p icmp --icmp-type 0/0 -j DROP

#Drop potential SQL Worm

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 1433 -j ACCEPT

iptables -A FORWARD -p tcp --dport 1433 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Possible SQL Worm: "

iptables -A FORWARD -p tcp --dport 1433 -j DROP

#Pass all boxes to the keep_state chain

iptables -A FORWARD -j KEEP_STATE

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

##Set up UDP

#Outgoing Traceroute

iptables -A FORWARD -p udp -s 192.168.9.0/24 --sport 32769:65535 --dport 33434:33523 -j ACCEPT

#Incoming Traceroute

iptables -A FORWARD -p udp -s 192.168.9.0/24 --dport 32769:65535 --sport 33434:33523 -j ACCEPT

#Time exceeded

iptables -A FORWARD -p udp -s 192.168.9.0/24 --dport 11 -j ACCEPT

#Port not found

iptables -A FORWARD -p udp -s 192.168.9.0/24 --dport 3 -j ACCEPT

#DNS

iptables -A FORWARD -p udp -s 192.168.9.0/24 --dport 53 -j ACCEPT

#SNMP

iptables -A FORWARD -p udp -s 192.168.9.0/24 --dport 161 -j ACCEPT

#DHCP

iptables -A FORWARD -p udp -s 192.168.9.0/24 --sport 68 --dport 67 -j ACCEPT

#Time Server

iptables -A FORWARD -p udp -s 192.168.9.0/24 --sport 1024:65535 --dport 123 -j ACCEPT

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

##Allow outward browsing

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 80 -j ACCEPT

##Allow outward ssh

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 22 -j ACCEPT

##Allow outward ftp

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 21 -j ACCEPT

##Allow outward telnet

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 23 -j ACCEPT

##Allow outward smtp

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 25 -j ACCEPT

##Allow outward pop

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 110 -j ACCEPT

###Block HTTP Request from outside that are not authorized

iptables -A FORWARD -p tcp --dport 80 -j DROP

iptables -A FORWARD -p tcp --dport 80 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Dropped HTTP: "

#Allow Telnet out

iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 23 -j ACCEPT

#Deny ports

##telnet

iptables -A FORWARD -p tcp --dport 23 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Denied Telnet: "

#Deny ports

##telnet

iptables -A FORWARD -p tcp --dport 23 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Denied Telnet: "

iptables -A FORWARD -p tcp --dport 23 -j DROP

##Deny BO

iptables -A FORWARD -p udp --dport 31337 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Denied BO: "

iptables -A FORWARD -p udp --dport 31337 -j DROP

#Deny and log ftp on all others

#iptables -A FORWARD -p tcp -s 192.168.9.0/24 --dport 21 -j DROP

#iptables -A FORWARD -p tcp --dport 21 -m limit --limit 5/minute -j LOG --log-level notice --log-prefix "Denied FTP: "

#Deny suspicious traffic

iptables -A FORWARD -p tcp --destination-port 1080 -j DROP

iptables -A FORWARD -p tcp --destination-port 8080 -j DROP

iptables -A FORWARD -p tcp --destination-port 8000 -j DROP

iptables -A FORWARD -p tcp --destination-port 8081 -j DROP

##Allow all outgoing traffic

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3128 (轉發至squid)

iptables -A FORWARD -s 192.168.9.0/24 -j ACCEPT

#Set to drop all packets not accepted by rules above

iptables -A FORWARD -j DROP

也把它放到/etc/init.d中,這樣就可以隨著xinet.d一起啟動了。iptables的語法這裡就不詳細說了,網上很多。

最後就是squid的配置,這需要仔細說一下,隨RH發布的squid的配置有問題,性能受限。建議先卸除,到www.squid-cache.org下載最新的2.5stable1。然後重新編譯,編譯前需做以下準備工作:

1。編輯/usr/include/bits/types.h中__FD_SETSIZE值至32768

2。ulimit -HSn 32768

然後到squid src包目錄編譯squid ,./configure, make all, make install.....

squid會安裝在預設的/usr/local/squid下,squid的可執行文件在安裝目錄的bin子目錄下,配置文件在etc子目錄下

Squid配置文件為:/usr/local/squid/etc/squid.conf,以下為我的配置:

http_port 8080

cache_mem 32 MB

cache_swap_low 90

cache_swap_high 95

maximum_object_size 4096 KB

cache_dir ufs /usr/local/squid/cache 10000 16 256

cache_access_log /usr/local/squid/logs/access.log

cache_log /usr/local/squid/logs/cache.log

dns_nameservers 202.96.209.5

unlinkd_program /usr/local/squid/bin/unlinkd

acl acllist src 192.168.9.0/255.255.255.0

acl regular_days time MTWHF 8:00-19:00

acl movie urlpath_regex "/etc/squid/banned.list"(把過濾關鍵字寫到文件中去)

acl banned url_regex iij4u.or.jp(做些控制)

acl cache_prevent1 url_regex cgi-bin /?

acl cache_prevent2 url_regex Servlet

acl all src 0.0.0.0/0.0.0.0

acl manager proto cache_object

acl localhost src 127.0.0.1/255.255.255.255

acl SSL_ports port 443 563

acl Safe_ports port 80 # http

acl Safe_ports port 21 # ftp

acl Safe_ports port 443 563 # https, snews

acl Safe_ports port 70 # gopher

acl Safe_ports port 210 # wais

acl Safe_ports port 1025-65535 # unregistered ports

acl Safe_ports port 280 # http-mgmt

acl Safe_ports port 488 # gss-http

acl Safe_ports port 591 # filemaker

acl Safe_ports port 777 # multiling http

http_access deny movie regular_days

no_cache deny cache_prevent1

no_cache deny cache_prevent2

http_access deny banned

http_access allow all

http_access deny !Safe_ports

http_access deny CONNECT !SSL_ports

icp_access allow all

http_access allow manager localhost

http_access deny manager

http_access allow localhost

http_access deny all

client_lifetime 2 hours

half_closed_clients off

cache_effective_user squid

cache_effective_group squid(請注意squid對cache及log目錄有讀寫權)

httpd_accel_host virtual

httpd_accel_port 80

httpd_accel_with_proxy on

httpd_accel_uses_host_header on

同時在/etc/init.d中的啟動腳本里加上這句ulimit -HSn 32768

這樣squid啟動時在cache.log中就可以看到如此語句:

2003/03/05 09:30:53| Starting Squid Cache version 2.5.STABLE1-20030303 for i686-pc-linux-gnu...

2003/03/05 09:30:53| Process ID 12939

2003/03/05 09:30:53| With 32768 file descriptors available

此時的squid擁有32768個file descriptors(預設為1024),如果用戶很多,預設值會成為瓶頸,極度影響squid的速度(它會報錯說running out of file descriptors),我曾經在板上發問,結果沒人理我(,還是自力更生,豐衣足食。

啟動squid:/usr/local/squid/bin/squid -D

大功告成!整個出internet的http流量就全朝squid走了,用戶不知道,同時又可完成封鎖的功能。

好辛苦啊!

[火星人 ] 透明防火牆架設的完全攻略(bridge+iptables+squid)已經有613次圍觀

http://coctec.com/docs/linux/show-post-203891.html