Linux socket設定mark的必要性 Linux的Netfilter鉤子點的位置會導致一些奇怪的問題,比如本機發出的包無法使用基於mark的策略路由,這是因為mark一般是在Netfilter中進行的,而Linux的路由處在OUTPUT鉤子點之前,因此這是一個順序倒置的問題,如何來解決呢?只能在路由之前打上mark,而我們知道,對於外部進入的包,mark是在PREROUTING進行的,因此對於外部進入的包,策略路由是好使的,對於本機發出的包,路由之前只能是socket層了,那為何不能在傳輸層做呢?因為一來傳輸層比較雜,二來很多協議直接走到IP層,比如OSPF之類的,三來很多傳輸層協議也需要路由尋找,比如TCP在connect的時候就需要尋找路由以確定源IP地址(如果沒有bind的話)。
幸運的是,Linux的socket支援SO_MARK這樣一個option,可以很方便的使用:[plain]mark = 100; setsockopt(client_socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark));
1.對TRACK的影響 www.2cto.com 雖然raw表是資料包經過的第一個表,使用SO_MARK仍然可以在整個raw表起作用之前做點mark,從而使得一個特定socket發出的包統統NOTRACK:iptables -t raw -A OUTPUT -m mark --mark 100 -j NOTRACK
如果不這樣的話,就需要:iptables -t raw -A OUTPUT [-s xxxx] [-d yyyy] [-p tcp|udp [--sport X] [--dport Y] ... -j MARK --set-mark 100...[一大堆和上面類似的規則]iptables -t raw -A OUTPUT -m mark --mark 100 -j NOTRACK正如在PREROUTING上的raw表需要做的那樣。我們得意於OUTPUT上面是socket,是應用程式的世界,而PREROUTING以下則是核心以及驅動的世界了,後者太雜太亂,不便做更多的事,而前者則是我們可以掌控的範圍。 2.對策略路由的影響SO_MARK最大的受益者就是策略路由了,如果我們這是以下的路由:ip rule add fwmark 100 table abc www.2cto.com ip route add 1.2.3.4/32 via 192.168.0.254 table abcip route del 1.2.3.4/32 table main
不設定SO_MARK的情況下,所有的訪問1.2.3.4的流量將因為沒有路由而被丟棄,因為在進入PREROUTING前首先要尋找路由,而此時還沒有打上mark,因而不會匹配到abc策略表中的那條路由,而main表中的對應路由我們已經刪除了...但是如果我們在應用程式中加入:[plain]mark = 100; setsockopt(client_socket, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); 訪問就可以正常了,因為在尋找路由的時候,已經有這個mark了。 作者 dog250