ファイアーウォールを作る!セキュリティを高めよう

この記事を読むのに掛かる時間: 24

目次

  1. ファイアーウォールを作る!セキュリティを高めよう
    1. どうゆう環境で?
    2. Linux カーネル
  2. 動作原理
  3. firewall
  4. droplist
  5. 確認
  6. ダウンロード

ファイアーウォールを作る~セキュリティを高めよう

防火壁です:-)
Linux IP Connection Tracking Modules を利用して,製品レベルの firewall を設計します(とゆうか,製品にはまさにそのもの現物が使われています).
いつの間にやら複雑化してしまいましたが…
使えそうなら適当に改造して使って下さい.

スポンサーリンク
336×280

どうゆう環境で?

2つのI/Fをブリッジしている環境向けです.
例えば,有線ネットワークを無線に繋いでいるイーサネットコンバーターや pppoe で ISP にアップリンクしているルーター機の場合など.
この場合,EXT=wlan0 を ppp+ などに適宜書き換えて下さい.
私は Orange Pi の様なシングルボードコンピューターをイーサネットコンバータとして使い,この firewall を走らせています.

Linux カーネル

一般的なディストリビューションなら大丈夫の筈ですが,カーネルモジュール,特に特定の LOG ターゲットなどへのモジュールがないと怒られるかも.
その場合は .config 調節してカーネルリコンパイルか,そのターゲットを使わない様に改造するとかですね.

動作原理

どうゆう設計思想でどうゆう動作原理かは…
説明したいのですが,めちゃめちゃ長くなるので,次回以降にでも(–;;
詳しくはソースを追いながら iptables のマニュアルなどを参照して下さい.
ものすごく大雑把に説明すると,

  • 基本的に入ってくるパケットも出ていくパケットもすべて拒否し
  • 厳密に指定したパケットのみを許可する.
  • 見通し向上と扱いやすくする為に IN/OUT でチェーンを分ける.
  • IP Connection Tracking Modules の機能で NEW,ESTABLISHED と ESTABLISHED を区別し,
  • 開いたポートを追跡してその要求に対応するポートのみ許可する.
  • なりすまし防止とか

みたいな.

※あまりにも厳密にブロックするので,何かが動かないときの原因はたいていコイツです(笑).

firewall

    #! /bin/sh

    ## ポリシー設定.
    DEFAULT_POLICY_INPUT='DROP'
    DEFAULT_POLICY_OUTPUT='DROP'
    DEFAULT_POLICY_FORWARD='DROP'

    ## ローカルの定義.
    LOCAL='192.168.0.0/16'

    ## どこでも.
    ANY='0/0'

    ## external IF.
    EXT='wlan0'

    ## local IF.
    INT='eth0'

    ## wireless 特権許可.親routerに繋がっているタブレットなど用.
    #EXT_MINE='192.168.1.126'

    ## 追加のリスト読込. 巨大ファイルはアップリンク時のタイムアウトに注意.
    #DROPLIST='./DROPLIST'

    ## ドロップリストをログするかどうか.
    #LOG_DROPLIST=1

    ## ローカルアドレス.偽造されたらログして捨てる.
    SPOOFING='
    224.0.0.0/4 
    240.0.0.0/5 
    10.0.0.0/8 
    127.0.0.0/8 
    172.16.0.0/12 
    '
    ## デバッグ用.マーカー出力
    #DEBUGMODE=1

    ## デバッグ用.INPUT,OUTPUT チェインをログするかどうか.
    #DEBUGLOG=1
    #LOGADDR='192.168.10.10/24'

    ## くだらない攻撃などをログするかどうか.
    #LOG_JUNK_PACKETS=1

    ## ウイルス等の自動スキャンに使われるポート.ログしない.パケットは破棄される.
    VIRUSPORTS='137 445 1433 17300'
    ## 137: ??, 445: DELODER, Windows trojan, 1433: Spida, SQL worm, 17300: Kuang2

    ## 外部からアクセスを許可するポート.
    INPORTS='
    '

    ## 外部へのアクセスを許可するポート.
    OUTPORTS='
    22 
    25 
    42 
    43 
    53&proto=tcp 
    53&proto=udp 
    80 
    113 
    123&proto=udp 
    143 
    443 
    587 
    873 
    995 
    11371 
    '

    ## 追加のオプションが必要な時は & で区切る.追加出来るオプションは以下の通り.
    ## inchain= ルールを追加するチェイン.
    ## outchain= ルールを追加するチェイン.
    ## src= 接続元IP
    ## proto= プロトコル.tcp,udp,icmp,all 等.
    ## state= 二つ以上追加する時は , で区切る.
    ##    20: ftp-data
    ##    21: ftp
    ##    22: ssh
    ##    23: telnet
    ##    25: smtp
    ##    42: name
    ##    43: whois
    ##    53: named
    ##    80: www
    ##   110: pop3
    ##   113: auth
    ##   123: ntp
    ##   143: imap
    ##   443: https
    ##   587: submission port
    ##   873: rsync
    ##   995: pop for gmail
    ##  6660: irc
    ##  8080: delegate
    ##  8123: polipo
    ##  9050:9051: Tor
    ## 11371: hkp gnupg
    ## 49999: rtorrent
    ## ---------------------------------------------------------------------------------
    ## 全ルール消去,空チェイン削除,カウンタリセット.
    [ ! -z ${DEBUGMODE} ] && echo '>> reset...'
    iptables -F -t nat
    iptables -F
    iptables -X
    iptables -Z

    ## ポリシー設定.
    [ ! -z ${DEBUGMODE} ] && echo '>> set policy...'
    iptables -P INPUT ${DEFAULT_POLICY_INPUT}
    iptables -P OUTPUT ${DEFAULT_POLICY_OUTPUT}
    iptables -P FORWARD ${DEFAULT_POLICY_FORWARD}

    ## マスカレード.
    [ ! -z ${DEBUGMODE} ] && echo '>> set masq...'
    iptables -A FORWARD -s ${LOCAL} -j ACCEPT
    iptables -A FORWARD -d ${LOCAL} -j ACCEPT
    iptables -t nat -A POSTROUTING -o ${EXT} -j MASQUERADE

    ## NAT
    #iptables -t nat -A PREROUTING -i ${EXT} --dport 843       -j DNAT --to-destination 192.168.10.10
    #iptables -t nat -A PREROUTING -i ${EXT} --dport 991:999   -j DNAT --to-destination 192.168.10.10
    #iptables -t nat -A PREROUTING -i ${EXT} --dport 8094:8099 -j DNAT --to-destination 192.168.10.10

    ## NAT を有効に.
    [ ! -z ${DEBUGMODE} ] && echo '>> NAT enable...'
    echo 1 > /proc/sys/net/ipv4/ip_forward

    ## I/O: ループバック内を全て許可.
    [ ! -z ${DEBUGMODE} ] && echo '>> accept loopback...'
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A OUTPUT -o lo -j ACCEPT

    ## I/O: ローカル内を全て許可.
    [ ! -z ${DEBUGMODE} ] && echo '>> accept local...'
    iptables -A INPUT -i ${INT} -s ${LOCAL} -j ACCEPT
    iptables -A OUTPUT -o ${INT} -d ${LOCAL} -j ACCEPT

    ## ---------------------------------------------------------------------------------
    ## I/O: 攻撃分離チェーン作成,適用.
    [ ! -z ${DEBUGMODE} ] && echo '>> make filter chain...'
    iptables -N filter
    iptables -A INPUT -i ${EXT} -j filter

    ## IN: spoofing.
    [ ! -z ${DEBUGMODE} ] && echo '>> for spoofing...'
    for SRC in ${SPOOFING}
    do
        [ ! -z ${LOG_JUNK_PACKETS} ] && iptables -A filter -i ${EXT} -s ${SRC} -j LOG --log-prefix 'FILTER-SPOOFING:'
        iptables -A filter -i ${EXT} -s ${SRC} -j DROP
    done

    ## I/O: ping of death.
    [ ! -z ${DEBUGMODE} ] && echo '>> for ping of death...'
    iptables -A filter -p icmp --icmp-type echo-request -m limit --limit 1/s  -j ACCEPT
    [ ! -z ${LOG_JUNK_PACKETS} ] && iptables -A filter -p icmp --icmp-type echo-request -j LOG --log-prefix 'FILTER-PING-OF-DEATH:'
    iptables -A filter -p icmp --icmp-type echo-request -j DROP

    ## I/O: port scaner.
    [ ! -z ${DEBUGMODE} ] && echo '>> for port scaner...'
    iptables -A filter -p tcp --tcp-flag SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT
    [ ! -z ${LOG_JUNK_PACKETS} ] && iptables -A filter -p tcp --tcp-flag SYN,ACK,FIN,RST RST -j LOG --log-prefix 'FILTER-PORT-SCAN:'
    iptables -A filter -p tcp --tcp-flag SYN,ACK,FIN,RST RST -j DROP

    ## I/O: syn flood.
    [ ! -z ${DEBUGMODE} ] && echo '>> for syn flood...'
    iptables -A filter -p tcp --syn -m limit --limit 1/s --limit-burst 8 -j ACCEPT
    [ ! -z ${LOG_JUNK_PACKETS} ] && iptables -A filter -p tcp --syn -j LOG --log-prefix 'FILTER-SYN-FLOOD:'
    iptables -A filter -p tcp --syn -j DROP

    ## I/O: ウイルス等の既知の自動スキャンを破棄.
    [ ! -z ${DEBUGMODE} ] && echo '>> for virusports...'
    if [ ! -z "${VIRUSPORTS}" ];then
        for PORT in ${VIRUSPORTS}
        do
            iptables -A filter -p tcp --dport ${PORT} -j DROP
            iptables -A filter -p udp --dport ${PORT} -j DROP
        done
    fi

    ## ---------------------------------------------------------------------------------
    ## wireless 特権許可
    [ ! -z ${DEBUGMODE} ] && echo '>> accept wireless mine...'
    if [ ! -z ${EXT_MINE} ];then
        iptables -A INPUT -s ${EXT_MINE} -j ACCEPT
        iptables -A OUTPUT -d ${EXT_MINE} -j ACCEPT
    fi

    ## I/O: gate (一時的に追加するルール等を入れる)
    [ ! -z ${DEBUGMODE} ] && echo '>> make gate chain...'
    iptables -N gate
    iptables -A INPUT -i ${EXT} -j gate
    iptables -A OUTPUT -o ${EXT} -j gate

    ## I/O: 落すアドレスのログ保存専用チェーン作成.
    [ ! -z ${DEBUGMODE} ] && echo '>> make gate-log chain...'
    iptables -N gate-log
    [ ! -z ${LOG_DROPLIST} ] && iptables -A gate-log -j LOG --log-prefix 'GATE-DENY-ADDRESS:'
    iptables -A gate-log -j DROP

    ## I/O: 落すアドレスをゲートチェーンに入れる.
    if [ "${1}" = 'drop' ];then
        source ${DROPLIST}
        for LST in ${DENYADDRESS}
        do
            iptables -A gate -s ${LST} -i ${EXT} -j gate-log
        done
    fi

    ## I/O: wlan 分離して INPUT, OUTPUT から遠ざける.
    [ ! -z ${DEBUGMODE} ] && echo '>> make wlan-out chain...'
    iptables -N wlan-in
    iptables -N wlan-out
    iptables -A INPUT -i ${EXT} -j wlan-in
    iptables -A OUTPUT -o ${EXT} -j wlan-out

    ## デバッグログの取得.
    if [ ! -z ${DEBUGLOG} ];then
        [ -z ${LOGADDR} ] && LOGADDR=${ANY}
        iptables -A wlan-in -s ${LOGADDR} -j LOG --log-prefix 'DEBUG-INPUT:'
        iptables -A wlan-out -d ${LOGADDR} -j LOG --log-prefix 'DEBUG-OUTPUT:'
    fi

    ## OUT: ping を許可.
    [ ! -z ${DEBUGMODE} ] && echo '>> accept ping/pong/traceroute...'
    iptables -A wlan-out -p icmp -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
    ## IN: pong を許可.
    iptables -A wlan-in  -p icmp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    ## OUT: traceroute を許可.
    iptables -A wlan-out -p udp --dport 33434:33534 -m conntrack --ctstate NEW -j ACCEPT

    ## ---------------------------------------------------------------------------------
    ## IN: 外側からのアクセスを許可.
    [ ! -z ${DEBUGMODE} ] && echo '>> accept ports from external...'
    for LST in ${INPORTS}
    do
        INCHAIN='wlan-in'; OUTCHAIN='wlan-out'; SRC=${ANY}; PROTO='tcp'; PORT=''; STATE='';
        if (echo ${LST} | grep -i 'inchain' > /dev/null);then
            INCHAIN=echo ${LST} | sed -e 's/.*inchain=\([0-9a-z\-_]*\).*/\1/i'
        fi
        if (echo ${LST} | grep -i 'outchain' > /dev/null);then
            OUTCHAIN=echo ${LST} | sed -e 's/.*outchain=\([0-9a-z\-_]*\).*/\1/i'
        fi
        if (echo ${LST} | grep -i 'src' > /dev/null);then
            SRC=echo ${LST} | sed -e 's/.*src=\([0-9a-z\.\/]*\).*/\1/i'
        fi
        if (echo ${LST} | grep -i 'proto' > /dev/null);then
            PROTO=echo ${LST} | sed -e 's/.*proto=\([a-z\.]*\).*/\1/i'
        fi
        PORT=echo ${LST} | sed -e 's/^\([0-9a-z:]*\).*$/\1/i'
        if (echo ${LST} | grep -i 'state' > /dev/null);then
            STATE=,echo ${LST} | sed -e 's/.*state=\([A-Z,]*\).*/\1/'
        fi
        iptables \
            -A ${INCHAIN} \
            -s ${SRC} \
            -p ${PROTO} \
            --dport ${PORT} \
            -m conntrack \
            --ctstate NEW,ESTABLISHED${STATE} \
            -j ACCEPT
        iptables \
            -A ${OUTCHAIN} \
            -d ${SRC} \
            -p ${PROTO} \
            --sport ${PORT} \
            -m conntrack \
            --ctstate ESTABLISHED${STATE} \
            -j ACCEPT
    done

    ## ---------------------------------------------------------------------------------
    ## OUT: 外側へのアクセスを許可.
    [ ! -z ${DEBUGMODE} ] && echo '>> accept ports to external...'
    for LST in ${OUTPORTS}
    do
        INCHAIN='wlan-in'; OUTCHAIN='wlan-out'; SRC=${ANY}; PROTO='tcp'; PORT=''; STATE='';
        if (echo ${LST} | grep -i 'inchain' > /dev/null);then
            INCHAIN=echo ${LST} | sed -e 's/.*inchain=\([0-9a-z\-_]*\).*/\1/i'
        fi
        if (echo ${LST} | grep -i 'outchain' > /dev/null);then
            OUTCHAIN=echo ${LST} | sed -e 's/.*outchain=\([0-9a-z\-_]*\).*/\1/i'
        fi
        if (echo ${LST} | grep -i 'src' > /dev/null);then
            SRC=echo ${LST} | sed -e 's/.*src=\([0-9a-z\.\/]*\).*/\1/i'
        fi
        if (echo ${LST} | grep -i 'proto' > /dev/null);then
            PROTO=echo ${LST} | sed -e 's/.*proto=\([a-z\.]*\).*/\1/i'
        fi
        PORT=echo ${LST} | sed -e 's/^\([0-9a-z:]*\).*$/\1/i'
        if (echo ${LST} | grep -i 'state' > /dev/null);then
            STATE=,echo ${LST} | sed -e 's/.*state=\([A-Z,]*\).*/\1/'
        fi
        iptables \
            -A ${OUTCHAIN} \
            -d ${SRC} \
            -p ${PROTO} \
            --dport ${PORT} \
            -m conntrack \
            --ctstate NEW,ESTABLISHED${STATE} \
            -j ACCEPT
        iptables \
            -A ${INCHAIN} \
            -s ${SRC} \
            -p ${PROTO} \
            --sport ${PORT} \
            -m conntrack \
            --ctstate ESTABLISHED${STATE} \
            -j ACCEPT
    done

    ## ---------------------------------------------------------------------------------
    ## IN: それら以外に入って来るパケットを記録して破棄.
    [ ! -z ${DEBUGMODE} ] && echo '>> logging drops...'
    iptables -A wlan-in -j LOG --log-prefix 'WLAN-IN-DROP:'

    ## OUT: 未知の新規パケットを特に記録,
    if [ ! ${DEFAULT_POLICY_OUTPUT} = 'ACCEPT' ];then
        iptables -A wlan-out -p tcp --syn -m conntrack --ctstate NEW -j LOG --log-prefix 'WLAN-OUT-DROP-NEW:'
        iptables -A wlan-out -j LOG --log-prefix 'WLAN-OUT-DROP:'
    fi

droplist

こんな感じでリストにする.
./DROPLIST.src

    DENYADDRESS='
    207.68.128.0/18 
    207.68.192.0/20 
    '

確認

# iptables -L -n

ダウンロード

本体: firewall.src 一行目と最終行を削除してね.
落とすリスト:DROPLIST.src 大陸とかからの執拗な攻撃をまとめてばっさり拒否.

スポンサーリンク
336×280
336×280

書いた人

me 小津雪ヲ: 生きるとゆう事は,雑多な問題に対処するとゆう事.
ライフハック,DIY,木工,鉄工,ソルトルアー,ロードバイク,オートバイ,家庭菜園,自給自足,料理,Linux,ガジェット,写真,フラメンコギターなど.
日常の様々な創意工夫やお役立ち情報を発信しています.

記事のシェア,ツイッターフォロー,ブックマーク,RSS登録 お願いします.
あとランキングも押して頂けると助かりますm(__)m

ブログランキング・にほんブログ村へ blogranking
blogranking

シェアする

フォローする