iptables路由轉發及控制


基於狀態的iptables(就是一個包過濾的條件)

包過濾的條件:
如: 
-p 協議  
-sport/dport xxx   
-s/-d xxxx   
-m state --state 狀態


如果按照tcp/ip來划分連接狀態,有11種之多
但iptables里只有4種狀態;ESTABLISHED、NEW、RELATED及INVALID

這兩個分類是兩個不相干的定義。例如在TCP/IP標准描述下UDP及ICMP數據包是沒有連接狀態的,但在state模塊的描述下,任何數據包都有連接狀態。


    1、ESTABLISHED
   
    (1)與TCP數據包的關系:首先在防火牆主機上執行SSH Client,並且對網絡上的SSH服務器提出服務請求,而這時送出的第一個數據包就是服務請求的數據包,如果這個數據包能夠成功的穿越防火牆,那么接下來SSH Server與SSH Client之間的所有SSH數據包的狀態都會是ESTABLISHED。

    (2)與UDP數據包的關系:假設我們在防火牆主機上用firefox應用程序來瀏覽網頁(通過域名方式),而瀏覽網頁的動作需要DNS服務器的幫助才能完成,因此firefox會送出一個UDP數據包給DNS Server,以請求名稱解析服務,如果這個數據包能夠成功的穿越防火牆,那么接下來DNS Server與firefox之間的所有數據包的狀態都會是ESTABLISHED。
    (3)與ICMP數據包的關系:假設我們在防火牆主機ping指令來檢測網絡上的其他主機時,ping指令所送出的第一個ICMP數據包如果能夠成功的穿越防火牆,那么接下來剛才ping的那個主機與防火牆主機之間的所有ICMP數據包的狀態都會是ESTABLISHED。
    由以上的解釋可知,只要第一個數據包能夠成功的穿越防火牆,那么之后的所有數據包(包含反向的所有數據包)狀態都會是ESTABLISHED。

    2、NEW
   
    首先我們知道,NEW與協議無關,其所指的是每一條連接中的第一個數據包,假如我們使用SSH client連接SSH server時,這條連接中的第一個數據包的狀態就是NEW。

    3、RELATED

    RELATED狀態的數據包是指被動產生的數據包。而且這個連接是不屬於現在任何連接的。RELATED狀態的數據包與協議無關,只要回應回來的數據包是因為本機送出一個數據包導致另一個連接的產生,而這一條新連接上的所有數據包都是屬於RELATED狀態的數據包。

    4、INVALID

    INVALID狀態是指狀態不明的數據包,也就是不屬於以上三種狀態的封包。凡是屬於INVALID狀態的數據包都視為惡意的數據包,因此所有INVALID狀態的數據包都應丟棄掉,匹配INVALID狀態的數據包的方法如下:
    iptables -A INPUT -p all -m state INVALID -j DROP
    我們應將INVALID狀態的數據包放在第一條。


                    |
            隨機        |     80  web
            --------- |--》        
        client            |       server        
            《--------- |--
            隨機        |     80    
                    |

client訪問server過去
第一個數據包(new狀態),如果拒絕,那么后續包都會被拒絕(因為后面來的都會是第一個,都為new狀態)
第一個數據包如果允許過去,那么后續包的狀態為established



server返回給client
返回的所有包都為established



例1:
有下面兩台機

        10.1.1.2        10.1.1.3
         client              server        



10.1.1.2是可以ssh訪問10.1.1.3,也可以elinks訪問10.1.1.3

1,在10.1.1.3上
iptables -P INPUT DROP
iptables -P OUTPUT DROP
這里就把雙鏈都關掉,10.1.1.2任何訪問都過不來了

2,
按以前的做法
在10.1.1.3上允許別人ssh進來
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
在10.1.1.3上允許別人elinks進來
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

或者把上面四條合下面兩條
iptables -A INPUT -p tcp -m multiport  --dport 22,80 -j ACCEPT
iptables -A OUTPUT -p tcp -m multiport  --sport 22,80 -j ACCEPT


把上面的兩條再換成
iptables -A INPUT -p tcp -m multiport  --dport 22,80 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state established -j ACCEPT
(后面一句可以翻譯成tcp協議的連接只要你進得來,你就回得去)
(無論他是用哪個隨機端口訪問進來的;因為只要能進來,那么后續的包都屬於ESTABLISHED狀態)




例2:
有些服務器,可能希望客戶端ping不通此服務器,但是此服務器可以ping通客戶端(前提是客戶端沒有防火牆限制)

方法一:
在服務器上把/proc/sys/net/ipv4/icmp_echo_ignore_all的值改為1
臨時修改兩種方式:

echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all

sysctl -w net.ipv4.icmp_echo_ignore_all=1

永久修改
# vim /etc/sysctl.conf    --加上下面一句
net.ipv4.icmp_echo_ignore_all = 1
# sysctl -p    --使用此命令讓其生效



方法二:
通過iptables的狀態來實現
有下面兩台機

10.1.1.2        10.1.1.3

實現10.1.1.3這個IP能ping通所有人.但所有人不能ping通10.1.1.3

                    |
                --------------》|  ------->
          client        |  server        
              10.1.1.2        |  10.1.1.3
                  <-------------|  <--------   


                   NEW       ESTABLISHED
            INPUT       拒絕       允許
            OUTPUT       允許       允許


1,在10.1.1.3上
iptables -P INPUT DROP
iptables -P OUTPUT DROP
這里就把雙鏈都關掉,10.1.1.2任何訪問都過不來了


2,在10.1.1.3上
iptables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT

--重點是INPUT那條不能允許NEW狀態的;
--注意第二步的第二條(也就是output這條),如果只寫了NEW狀態,那么10.1.1.3ping所有人,都只能通第一個包;加上ESTABLISHED狀態,所有包都能通    



例3:
有一個服務器,搭建了http,ftp(主動和被動都要支持,被動端口為3000-3005)兩個服務(需要開放給所有人訪問),還要開放ssh和ping(但只開放給一個管理ip訪問,比如此IP為10.1.1.X),其它任何進來的訪問都拒絕
但此服務器要出去訪問別的任何服務,自己的防火牆都要允許


需求一個一個的寫
iptables -P INPUT DROP
iptables -P OUTPUT DROP

iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 20 -j ACCEPT

iptables -A INPUT -p tcp --dport 3000:3005 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 3000:3005 -j ACCEPT 

iptables -A INPUT -p tcp --dport 22 -s 10.1.1.X -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -d 10.1.1.X -j ACCEPT

iptables -A INPUT -p icmp -s 10.1.1.X -j ACCEPT
iptables -A OUTPUT -p icmp -d 10.1.1.X -j ACCEPT

iptables -A OUTPUT -p all -m state --state new,established,related -j ACCEPT
iptables -A INPUT -p all -m state --state established,related -j ACCEPT


需求綜合起來寫
iptables -P INPUT DROP
iptables -P OUTPUT DROP

iptables -A INPUT -p tcp -m mutliport --dport 80,21,20,3000,3001,3002,3003,3004,3005 -j ACCEPT

iptables -A INPUT -p tcp --dport 22  -s 10.1.1.X -j ACCEPT

iptables -A INPUT  -p icmp -s 10.1.1.X -j ACCEPT

iptables -A OUTPUT -p all -m state --state new,established,related -j ACCEPT
iptables -A INPUT -p all -m state --state established,related -j ACCEPT


=============================================================================


# 源A--B-->C目標



        A          B        

            交換機


        C          D


=============================================================================

路由
什么是交換,什么是路由,什么是路由表?
交換是指同網絡訪問(兩台機器連在同一個交換機上,配置同網段的不同ip就可以直接通迅)
路由就是跨網絡訪問(路徑選擇)
路由表是記錄路由信息的表(可以單路由表,也可以多路由表)


            因特網   ---》  物聯網(互聯網+)
  (無數個網絡組成,所以從一個網絡到另一個網絡,中間可能還要經過很多個網絡,必需要走路由)



我們現在討論的是單路由表,你在linux下用route -n查看

# route -n
Kernel IP routing table
 路由表                  網關              子網掩碼                                             網卡類型
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0                        0 br0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0                      0 br0
169.254.0.0     0.0.0.0         255.255.0.0     U     1003   0                  0 br0
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0                   0 br0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0                 0 virbr1
192.168.101.0   0.0.0.0         255.255.255.0   U     0      0                 0 virbr2
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0                 0 virbr0



問題1:按上面的路由表來看,如果我ping一個公網IP(如ping 14.215.177.38),應該怎么走?
答案:
我在本機訪問一個IP,先看目標ip是否為本地ip,如果是,則直接訪問本地;
如果不是,則找路由表里是否有你訪問的網段,有的話則從這個路由條目后面指定的網卡出去;
如果路由表里沒有你訪問的網段,則會找默認路由(也就是網關);
如果網關也沒有的話,則會報錯網絡不可達。


問題2:為什么route -n能看到這幾條路由(不同機器可能還不一樣)
答案:因為我對應的網卡有相關網段的ip,所以就會有對應的默認路由(比如我的機器br0網卡ip為10.1.1.1/24,所以我默認就會有10.1.1.0     0.0.0.0         255.255.255.0   U     0      0        0 br0 這一條路由)


問題3:如何加網關和刪除網關,加網關有什么要求?
route add default gw  x.x.x.x    --臨時加網關,馬上生效
route del default gw  x.x.x.x     --臨時刪網關,馬上生效
route add -net 4.4.4.0 netmask 255.255.255.0 dev eth1 --臨時加路由,馬上生效
route del  -net 4.4.4.0 netmask 255.255.255.0 dev eth1  --臨時刪除路由,馬上生效

永久加網關的方法
在網卡配置文件里/etc/sysconfig/network-scripts/ifcfg-br0
加一句GATEWAY=x.x.x.x;然后重啟network服務生效


加網關只能加你已經有的路由網段里的一個IP才行(ping不通此IP都可以)
加網關不需要指定子網掩碼(因為是已有的一個網段的ip,所以掩碼已經確認了)


問題4:如果你有br0:0這種子接口配置文件,那么每個文件里都要寫一個網關嗎?
准確來說:一個路由表上可以加多個網關,但只有一個生效(從上往下找,上面的優先生效;rhel6上面的網關不管通不通,都不會找下面的網關;centos7測試結果為上面的網關不能通,則自動找下面的網關;上面的網關可以通,則只會找上面的網關)。
但一台linux是可以做多路由表的,一個路由表一個有效網關,多路由表就是多個網關了。

# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.1.1.150       0.0.0.0         UG    0      0        0 br0
0.0.0.0         10.1.1.254       0.0.0.0         UG    0      0        0 br0
169.254.0.0     0.0.0.0         255.255.0.0     U     1010   0        0 br0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 br0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr1
192.168.101.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr2
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0



問題5:一台linux上如果有雙物理網卡,請問可不可以兩個網卡配置同網段的不同IP呢?
假設我的    eth0 10.1.1.5/24        
    eth1 10.1.1.6/24    

10.1.1.0     0.0.0.0         255.255.255.0   U     0      0        0  eth0
10.1.1.0     0.0.0.0         255.255.255.0   U     0      0        0  eth1


如果兩個網卡同網段,則會有下面兩條路由
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
10.1.1.0        0.0.0.0         255.255.255.0   U     0      0        0 eth1

它會實現從兩張網卡進來的包,卻從一張網卡出去,問題就產生了


domain name--->IP---->MAC
       dns    arp

把ip比喻成 "張三的家"
把MAC比喻成 "xx省xx市xx區xx街道xx小區xx單元xx室"


實驗:
步驟一:
一個虛擬機,開兩個網卡,都為橋接網絡,配置兩個IP,如下
# ip addr |grep eth 
2: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 52:54:00:41:e4:22 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.5/24 brd 10.1.1.255 scope global br0
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 52:54:00:39:c0:e6 brd ff:ff:ff:ff:ff:ff
    inet 10.1.1.6/24 brd 10.1.1.255 scope global eth1

步驟二:
在另一台機器(我這里為宿主機,ip為10.1.1.1),分別ping上面兩個ip,得到結果為兩個人的MAC都為第一個網卡的
# ip neigh |grep -E "^10.1.1.5 |^10.1.1.6 "
10.1.1.5 dev br0 lladdr 52:54:00:41:e4:22 REACHABLE
10.1.1.6 dev br0 lladdr 52:54:00:41:e4:22 REACHABLE


--按arp協議的原理,找誰誰才會回應mac地址(找張三,只能張三回應;找李四,只能李四回應)。而上面的實驗情況可以比喻成(張三,李四同一台機器,就是一家人,找張三,張三回,找李四,也張三回)


步驟三:
# vim /etc/sysctl.conf        --加上
net.ipv4.conf.eth0.arp_ignore = 1        
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.eth1.arp_ignore = 1        
net.ipv4.conf.eth1.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2

# sysctl -p   --用此命令讓其生效

這幾個參數的目的就是把上面的一家人(張三又回應張三也回應李四)的情況變成了原本的arp情況(張三只能回張三,李四只能回李四)



最終的效果的是宿主機只能ping通10.1.1.5了,ping不通10.1.1.6了(這就對了,因為一台機器雙網卡同網段會路由沖突)



=============================================================================


靜態路由
如下圖的實驗:
IP分配如下(掩碼假設全為24位),做實驗的話使用iptables -F把所有的防火牆規則清空
1.1.1.0/24網段用default來模擬
2.2.2.0/24網段用default1來模擬
3.3.3.0/24網段用default2來模擬
4.4.4.0/24網段用default3來模擬

        


VM1          VM2              VM3              VM4
         eth1(default1)       eth0(default1)     eth1(default3)
                  2.2.2.2    《--》    2.2.2.3            4.4.4.4  
    
         ip_forward          ip_forward

eth0 (default)     eth0(default)       eth1(default2)     eth0(default2)
1.1.1.1      --》      1.1.1.2           3.3.3.3     《--        3.3.3.4




sip:1.1.1.1    dip:4.4.4.4
返回
sip:4.4.4.4    dip:1.1.1.1



步驟一:
從1.1.1.1 ping 1.1.1.2

在宿主機上ping 1.1.1.2,能通

步驟二:
ping 2.2.2.2 不能通

解決方法:
在vm1上加網關
route add default gw 1.1.1.2

步驟三:
在宿主機加了一個網關指向1.1.1.2的基礎上,我再繼續在宿主機上ping 2.2.2.3 不能通 
解決方法:
在vm3上加網關指向2.2.2.2
route add default gw 2.2.2.2
還要在VM2上打開ip_forward,打開方法有三種
1,# echo 1 > /proc/sys/net/ipv4/ip_forward    --馬上生效,但重啟后就不生效了
2,# sysctl -w net.ipv4.ip_forward=1        --馬上生效,但重啟后就不生效了
3,# vim /etc/sysctl.conf    
net.ipv4.ip_forward = 1        --加這一句到此配置文件里
# sysctl -p            --保存后,使用此命令讓它永久生效



步驟四:
繼續ping 3.3.3.3    不通
解決:再在VM2上route add default gw 2.2.2.3

步驟五:
繼續ping 3.3.3.4    不通

解決:在VM3上打開ip_forward
還要在VM4上route add default gw 3.3.3.3

步驟六
繼續ping 4.4.4.4  不通
解決:如果在VM3上加一個網關指向3.3.3.4,其實是有問題的,因為VM3上這樣就有兩個網關了。如果你不使用多路由表的做法,這兩個網關只能有一個網關有效。
所以加網關的方式不可行,只能在VM3加路由
route add -net 4.4.4.0 netmask 255.255.255.0 dev eth1


上面終於從1.1.1.1ping到4.4.4.4


那么如果還有5網段,6網段,7網段,甚至更多(類似因特網),全部靠指網關來通迅不現實。實際的做法就是使用路由協議(rip,ospf,bgp等)來做,這就是動態路由了。



如果我把上面的所有網關和ip_forward去掉,然后手動加上路由(也就是說四台機都有四個網段的路由),那么就只能ping通到2.2.2.2,ping2.2.2.3就不通了


linux下可以安裝類似zebra這樣的軟路由軟件,可以把linux模擬成一台cisco路由器來進行配置。


============================================================================

准備三台虛擬機做實驗(把iptables都先關閉);
--注意:這里我沒有用宿主機模擬中間的機器(因為用宿主機有多個子接口的情況下,在做firewalld測試的時候會有不穩定的情況;而且宿主機打開firewalld,那么就會默認拒絕vnc等,帶來不方便)



    A                                             B(做路由只需要兩個不同ip)                       C

  內網(虛擬機)                            雙網卡機器(虛擬機)                                       外網(虛擬機)
            
192.168.100.128 -----》      192.168.100.2  eth1(default1)    
  (A主機的網卡信息也寫B主機的ip)
                                      ip_forward        
                                   # echo "1" > /proc/sys/net/ipv4/ip_forward   --臨時
                   10.1.1.2    eth0 (br0)    《----------------------  10.1.1.3(C機10段的ip設置為自己的網卡信息)
                            


--注意:模擬上面的環境時,宿主機可以模擬中間的雙網卡機器,但不能模擬內網或外網其中一台(原因是宿主機本來就是與虛擬的所有網段是直通的,你如果把它做為內網,則它會直接連接外網而不會走中間的網關)
--所以兩種模擬方法:1,宿主機模擬雙網卡機器,兩台虛擬機分別模擬內外網;2,不要宿主機,三台虛擬機來模擬,中間的雙網卡網關使用一台雙網關的虛擬機模擬,另兩台用單網卡來模擬


把gateway加上路由功能

# echo "1" > /proc/sys/net/ipv4/ip_forward   --臨時生效

# vim /etc/sysctl.conf 
net.ipv4.ip_forward = 1

# sysctl -p    --改完后使用此命令,使之修改永久生效

路由功能加了后,網關都指向了gateway這台物理機,那么  兩個網段的這兩台機就能互相ping通


例一:禁止內網192.168.100.128和外網10.1.1.3互ping
iptables -A FORWARD -p icmp -s 192.168.100.128 -j DROP
或者
iptables -A FORWARD -p icmp -s 10.1.1.3 -j DROP



例二:禁止內網192.168.100.128上外網的10.1.1.3這個網站
iptables -A FORWARD -p tcp --dport 80 -s 192.168.100.128 -d 10.1.1.3 -j DROP



=============================================================================




問題:這里我們模擬內外網的訪問,網關互指,中間雙網卡機器打開ip_forward,但實際的網絡訪問環境中,外網客戶會把網關指向你公司的網關嗎?

張三                     李四                   王五

  內網用戶             雙網卡機器             外網服務器
              (其實就是模擬一個路由器)
192.168.100.128    ---->  192.168.100.2   eth1    
                  網關指向    
                  打開ip_forward            

                      10.1.1.2       eth0                10.1.1.3

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM