[네트워크][보안] 클루닉스 내부 Bridge 서버 구축
Firewall + NAT를 동시에 지원하는 Bridge 구성을 위한 guide.
Bridge type의 장점 : FW 고장시 router에서 Hub로 직접 선을 연결하면 문제없이 사용
가능하다.
1. Bridge Firewall 구성
– Hardware
– 2 NIC
– 저 사양의 PC로 가능
– Network 구성
– GW <-> Bridge_FW <-> Hub <-> nodes
– Bridge_FW은 NAT(Masquerading)를 위해서 private ip하나와 public ip하나가
필요하다.
– private ip : 192.168.12.254
– public ip : 211.241.202.253
2. redhat 7.3 + compact rpm install
– bridge 구성을 위한 component
– kernel (bridge enabled) > 2.4.18-3
– bridge-utils-0.9.3-4.i386.rpm
3. Make Bridge
Bridge는 bridge-utils rpm에 있는 brctl로 bridge interface를 만든다. 두개의
NIC으로 하나의 bridge interface(br0)를 만들 수 있다.
brctl addbr br0
brctl addif br0 eth0
brctl addif br0 eth1
bridge는 기본적으로 두 개의 ethernet segment를 연결하는 장치로, 장비 자체의
주소는 필요없다. 하지만 firewall 관리 및 NAT를 위해 IP가 필요하다.
필요한 IP 설정은 bridge를 위한 script에서 설정한다.
– chkconfig –del network
– eth0, eth1은 ip를 갖지 않으므로 booting시에 사용하지 않는다.
/etc/sysconfig/network-scripts/ifcfg-eth{0,1}
/etc/sysconfig/network-scripts/ifcfg-eth1 :
# As eth0 will be tied to bridge(br0 interface),
# this must be activated with no IP addr
# Donghyun Kim <ryan@clunix.com> 2002.09.24
DEVICE=eth0
ONBOOT=no
/etc/sysconfig/network-scripts/ifcfg-eth1 :
# As eth1 will be tied to bridge(br0 interface),
# this must be activated with no IP addr
# Donghyun Kim <ryan@clunix.com> 2002.09.24
DEVICE=eth1
ONBOOT=no
– bridge interface에 public, private 두개의 ip를 지정한다.
/etc/sysconfig/network-scripts/ifcfg-{br0,br0:priv}
/etc/sysconfig/network-scripts/ifcfg-br0 :
# This is bridge interface tied with eth0/eth1
# bridge interface must be setup before activation by /etc/rc.d/init/bridge :
# – brctl addbr br0
# – brctl addif eth0
# – brctl addif eth1
# Donghyun Kim <ryan@clunix.com> 2002.09.24
DEVICE=br0
IPADDR=211.241.202.253
NETMASK=255.255.255.128
ONBOOT=yes
/etc/sysconfig/network-scripts/ifcfg-br0:priv :
# This is bridge interface tied with eth0/eth1
# bridge interface must be setup before activation :
# brctl addbr br0
# brctl addif eth0
# brctl addif eth1
# Donghyun Kim <ryan@clunix.com> 2002.09.24
DEVICE=br0:priv
IPADDR=192.168.12.254
NETMASK=255.255.255.0
ONBOOT=yes
– bridge interface를 만들고 lo, br0 interface를 ifup/ifdown을 사용하여
설정한다. 이때 bridge를 동작시키기 위해서는 br0, eth0, eth1 모두 UP
상태이어야 한다.
init-script style의 bridge를 다음과 같이 만든다.
/etc/rc.d/init.d/bridge :
#! /bin/sh
#
# bridge Start/Stop Ethernet Bridge interface with 2 ethernet NIC
#
# chkconfig: 2345 9 91
# description: Ethernet Bridge for transparent(bridge) Firewall
# make bridge interface(br0) and tie 2 NIC to br0 and
# setup firewall & NAT(MASQUERADE) of iptables
#
# Donghyun Kim <ryan@clunix.com> 2002.09.25
#
# Source function library.
. /etc/init.d/functions
# Source Network config
. /etc/sysconfig/network
# Check that networking is up.
if [ ${NETWORKING} = “no” ]
then
exit 0
fi
[ -x /usr/sbin/brctl ] || exit 0
RETVAL=0
start() {
# check /var/lock/subsys/bridge file
if [ -f /var/lock/subsys/bridge ] ; then
return
fi
# make bridge interface
echo -n $”Starting Bridge: ”
/usr/sbin/brctl addbr br0 > /dev/null 2>&1 &&
/usr/sbin/brctl addif br0 eth0 > /dev/null 2>&1 &&
/usr/sbin/brctl addif br0 eth1 > /dev/null 2>&1
RETVAL=$?
if [ $RETVAL -eq 0 ] ; then
success “bridge startup”
else
failure “bridge startup”
fi
echo
# start networking of bridge
echo -n $”Starting Network of Bridge: ”
ifup lo && ifconfig eth0 0.0.0.0 && \\
ifconfig eth1 0.0.0.0 && ifup br0
RETVAL=$?
[ $RETVAL -eq 0 ] && success “Network of bridge startup” || failure
“Network of bridge startup”
echo
touch /var/lock/subsys/bridge
return $RETVAL
}
stop() {
# check /var/lock/subsys/bridge file
if [ ! -f /var/lock/subsys/bridge ] ; then
return
fi
# stop networking of bridge
echo -n $”Stopping Network of bridge: ”
ifdown br0 && ifconfig eth1 down && ifconfig eth0 down && ifdown lo
RETVAL=$?
[ $RETVAL -eq 0 ] && success “Network of bridge stopping” || failure
“Network of bridge stopping”
echo
# stop bridge interface
echo -n $”Stopping Bridge: ”
/usr/sbin/brctl delif br0 eth1 > /dev/null 2>&1 &&
/usr/sbin/brctl delif br0 eth0 > /dev/null 2>&1 &&
/usr/sbin/brctl delbr br0 > /dev/null 2>&1
RETVAL=$?
if [ $RETVAL -eq 0 ] ; then
success “bridge stopping”
else
failure “bridge stopping”
fi
echo
rm -f /var/lock/subsys/bridge
return $RETVAL
}
# See how we were called.
case “$1” in
start)
start
;;
stop)
stop
;;
status)
/usr/sbin/brctl show
;;
restart)
stop
sleep 2
start
;;
*)
echo $”Usage: $0 {start|stop|status|restart}”
exit 1
esac
exit $RETVAL
– 먼저 bridge를 실행하여 network enable을 한 뒤에 iptables를 사용한
filtering을 구성한다.
1. default policy를 설정한다.
2. 명시적인 drop(refuse)시 로그를 남기고 REJECT를 위한 refuse chain 구성
3. 모든 internal node에 적용할 global protocol chain을 구성한다.
– icmp : icmp-type 0,3,5,8,11 accept
– udp : edonkey, 소리바다 accept
– tcp : MSN, edonkey, 소리바다 accept
4. ip_conntrack (stateful inspection) 기능으로 connection mapping을 유지
– “-m state –state …”
– internal -> external로 맺어진 connection을 tracking해서 쌍방향 유지
/etc/rc.d/init.d/firewall
#! /bin/sh
#
# firewall Start/Stop firewall with iptables
#
# chkconfig: 2345 99 99
# description: Clunix Firewall filtering & NAT with iptables
#
# Donghyun Kim <ryan@clunix.com> 2002.09.25
#
# Source function library.
. /etc/init.d/functions
# Source Network config
. /etc/sysconfig/network
# Check that networking is up.
if [ ${NETWORKING} = “no” ]
then
exit 0
fi
[ -x /sbin/iptables ] || exit 0
RETVAL=0
start() {
# check /var/lock/subsys/firewall file
if [ -f /var/lock/subsys/firewall ] ; then
return
fi
# print “start firewall” msg
echo -n $”Starting Firewall: ”
#
# start firewall & NAT
#
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp
echo 1 > /proc/sys/net/ipv4/ip_forward
#
# init iptables
#
# flush all chains
iptables -F
iptables -X
chains=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $chains
do
iptables -t $i -F
iptables -t $i -X
iptables -t $i -Z
done
######################################################################
# set default policies
######################################################################
# firewall itself : output only
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
# firewall filtering
iptables -P FORWARD DROP
######################################################################
# User defined chains
######################################################################
#
# refuse :
# explicit refuse chains
# logging to /var/log/firewall (via syslog kern.debug) & reject
#
iptables -N refuse
iptables -A refuse ! -i eth1 -m limit –limit 1/m -j LOG \\
–log-prefix “refused: ” –log-level debug
iptables -A refuse -p tcp -m limit –limit 10/s -j REJECT \\
–reject-with tcp-reset
iptables -A refuse -p udp -m limit –limit 10/s -j REJECT
iptables -A refuse -j DROP
#
# global_icmp :
# specified ICMP packets are accepted globally
#
# accept following icmp pkt
# – 0 : echo reply
# – 3 : dest unreachable
# – 5 : redirect
# – 8 : echo request
# – 11 : time exceed
iptables -N global_icmp
iptables -A global_icmp -p icmp –icmp-type 0 -j ACCEPT
iptables -A global_icmp -p icmp –icmp-type 3 -j ACCEPT
iptables -A global_icmp -p icmp –icmp-type 5 -j ACCEPT
iptables -A global_icmp -p icmp –icmp-type 8 -j ACCEPT
iptables -A global_icmp -p icmp –icmp-type 11 -j ACCEPT
#
# global_udp :
# specified udp packets are accepted globally
#
iptables -N global_udp
# edoneky (4661-4663/tcp, 4665/udp) for all PC
iptables -A global_udp -p udp –dport 4665 -j ACCEPT
#
# global_tcp :
# specified tcp packets (that is valid) are accepted globally
#
# specified tcp packets (that is valid) are accepted globally
#
iptables -N global_tcp
# accept tcp syn pkt
iptables -A global_tcp -p tcp –syn -j ACCEPT
# drop new pkt that has no syn
iptables -A global_tcp -p tcp ! –syn -m state –state NEW -j DROP
# MSN file transfer (6891-6900/tcp) for all PC
# http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q278887&
iptables -A global_tcp -p tcp –dport 6891:6900 -j ACCEPT
# edoneky (4661-4663/tcp, 4665/udp) for all PC
iptables -A global_tcp -p tcp –dport 4661:4663 -j ACCEPT
#
# open :
# accept connection by each server:port
#
iptables -N open
# ares (211.241.202.129) : smtp(25/tcp), wts(3389/tcp)
iptables -A open -p tcp -d 211.241.202.129 –dport 25 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.129 –dport 3389 -j ACCEPT
# dev (211.241.202.133) : ssh(22/tcp), dns(53/udp)
iptables -A open -p tcp -d 211.241.202.133 –dport 22 -j ACCEPT
iptables -A open -p udp -d 211.241.202.133 –dport 53 -j ACCEPT
# master (211.241.202.134) : ftp(21/tcp), ssh(22/tcp)
iptables -A open -p tcp -d 211.241.202.134 –dport 21 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.134 –dport 22 -j ACCEPT
# wts (211.241.202.245) : wts(3389/tcp)
iptables -A open -p tcp -d 211.241.202.245 –dport 3389 -j ACCEPT
# wts.manpa.net (211.241.202.135) : http(80/tcp) wts(3389/tcp)
iptables -A open -p tcp -d 211.241.202.135 –dport 80 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.135 –dport 3389 -j ACCEPT
# tech (211.241.202.221) : http(80/tcp), ftp(21/tcp)
iptables -A open -p tcp -d 211.241.202.221 –dport 80 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.221 –dport 21 -j ACCEPT
# 서진우 서버 (211.241.202.223) : ftp(21/tcp), ssh(22/tcp)
iptables -A open -p tcp -d 211.241.202.221 –dport 21 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.221 –dport 22 -j ACCEPT
# 서진우 PC 211.241.202.152 :
# ftp(21/tcp), ssh(22/tcp), http(80/tcp), wts(3389/tcp)
iptables -A open -p tcp -d 211.241.202.152 –dport 21 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.152 –dport 22 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.152 –dport 80 -j ACCEPT
# 기술팀 개인별 서버 : 서진우 요청
# 211.241.202.151,153,154,155 : wts(3389/tcp)
iptables -A open -p tcp -d 211.241.202.151 –dport 3389 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.153 –dport 3389 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.154 –dport 3389 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.155 –dport 3389 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.154 –dport 3389 -j ACCEPT
iptables -A open -p tcp -d 211.241.202.155 –dport 3389 -j ACCEPT
######################################################################
# FORWARD chain rules
######################################################################
# accept all packets from internal network (eth1)
iptables -A FORWARD -p ALL -i eth1 -j ACCEPT
# accept all packets from in/out according to stateful-inspection
iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT
# accept specified icmp packets by global_icmp chain
iptables -A FORWARD -p icmp -j global_icmp
# accept specified udp packets by global_udp chain
iptables -A FORWARD -p udp -j global_udp
# accept specified tcp packets by global_tcp chain
iptables -A FORWARD -p tcp -j global_tcp
# accept packets by server:port
iptables -A FORWARD -j open
# otherwise, refuse it
iptables -A FORWARD -j refuse
######################################################################
# INPUT/OUTPUT chain rules for firewall itself
# (211.241.202.253/192.168.12.254)
######################################################################
# br0 : ssh(22/tcp), global_icmp
# lo : accept all in/out
#
# accept all pkt from local loopback interface
iptables -A INPUT -i lo -j ACCEPT
# accept all packets by stateful-inspection
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
# filter by global icmp pkt
iptables -A INPUT -p icmp -j global_icmp
# filter by global tcp pkt
iptables -A INPUT -p tcp -j global_tcp
# accept only ssh(22/tcp) pkt
iptables -A INPUT -p tcp -i eth1 –dport 22 -j ACCEPT
# otherwise, refuse pkt
iptables -A INPUT -j refuse
# accept all out pkt
iptables -A OUTPUT -o br0 -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
######################################################################
# for NAT(masquerade) 192.168.12.0/24 -> 211.241.202.253 via firewall
######################################################################
#
# masquerade
#
iptables -t nat -A POSTROUTING -s 192.168.12.0/24 -j MASQUERADE
# print “firewall startup” msg
[ $? -eq 0 ] && success “firewall startup” || \\
# print “firewall startup” msg
[ $? -eq 0 ] && success “firewall startup” || \\
failure “firewall startup”
echo
# lock
touch /var/lock/subsys/firewall
}
stop() {
# check /var/lock/subsys/firewall file
if [ ! -f /var/lock/subsys/firewall ] ; then
return
fi
# print “stop firewall” msg
echo -n $”Stopping Firewall: ”
#
# flush & delete iptables rules
#
chains=`cat /proc/net/ip_tables_names 2>/dev/null`
for i in $chains
do
iptables -t $i -F
iptables -t $i -X
done
iptables -P INPUT ACCEPT && \\
iptables -P OUTPUT ACCEPT && \\
iptables -P FORWARD ACCEPT && \\
iptables -t nat -P PREROUTING ACCEPT && \\
iptables -t nat -P POSTROUTING ACCEPT && \\
iptables -t nat -P OUTPUT ACCEPT && \\
iptables -t mangle -P PREROUTING ACCEPT && \\
iptables -t mangle -P OUTPUT ACCEPT
#
# start firewall & NAT
#
echo 0 > /proc/sys/net/ipv4/ip_forward
rmmod ip_nat_ftp
rmmod ip_conntrack_ftp
# print “firewall stop” msg
[ $? -eq 0 ] && success “firewall stop” || failure “firewall stop”
echo
# unlock
rm -f /var/lock/subsys/firewall
}
# See how we were called.
case “$1” in
start)
start
;;
stop)
stop
;;
status)
/sbin/iptables -L INPUT
/sbin/iptables -L OUTPUT
/sbin/iptables -L FORWARD
;;
restart)
stop
sleep 1
start
;;
*)
echo $”Usage: $0 {start|stop|status|restart}”
exit 1
esac
exit $RETVAL