使用OpenVPN時的問題–用原始碼進行分析

來源:互聯網
上載者:User
使用OpenVPN時,有幾點需要注意:
1.如果不是OpenVPN用戶端將自己的虛擬IP地址作為源地址發出的資料包,而是由其forward的資料包,那麼就要在資料進入虛擬網卡之前做一個SNAT了,否則OpenVPN伺服器將會拒絕接收這種資料包;
2.如果使用的是tap虛擬網卡模式,那麼一定要將OpenVPN伺服器的虛擬ip設定成網關而不能僅僅設定一個出口裝置,因為tap模式需要進行arp,如果目的地址不在OpenVPN伺服器上或者即使在OpenVPN伺服器上但是其arp_ignore設定了不同的值,arp都會不成功進而無法發送資料;
3.在開啟了client-to-client的情況下並且使用tun模式時,不要以為所有的client和server均在同一子網內,tun是點對點的,沒有子網的概念,所以一個client或者其後的主機為了訪問另一個client c2後面的資源,不能將網關設定成c2,除非做複雜的源/目的地址轉換,因為OpenVPN伺服器將不認識c2後面的目的地址。
4.如果使用tap模式,並且開啟了c2c,那麼所有的client連同server共同組成一個虛擬子網,內部arp可流通,作為一個虛擬乙太網路和真實的乙太網路是一樣的,OpenVPN伺服器就是一個乙太網路交換器,可以設定任意的client或者server作為網關,這個意義上,OpenVPN伺服器是一個三層交換器。
具體的代碼都在multi_process_incoming_link中:
bool multi_process_incoming_link (struct multi_context *m, struct multi_instance *instance, const unsigned int mpp_flags)
{
struct context *c;
struct mroute_addr src, dest;
unsigned int mroute_flags;
struct multi_instance *mi;
bool ret = true;
...
if (BLEN (&c->c2.buf) > 0) {
process_incoming_link (c); //此操作進行解密,vpn作為客戶段來說只調用這一個函數而不進行下面的地址判斷
if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TUN) {
mroute_flags = mroute_extract_addr_from_packet (&src, //從ip資料報中解析出源/目的ip地址
&dest,
NULL,
NULL,
&c->c2.to_tun,
DEV_TYPE_TUN);
//確保源ip地址是自己的一個用戶端的,這就是說,要在用戶端進行源地址轉換
else if (multi_get_instance_by_virtual_addr (m, &src, true) != m->pending) {
...//列印錯誤記錄檔
c->c2.to_tun.len = 0; //不再往虛擬網卡寫入
} else if (m->enable_c2c) {
...//多播情況,tun模式下,通過判斷ip地址類型設定多播標誌,tun沒有arp
else { //以目的ip地址作為索引值尋找以目的地址為虛擬位址的自己的用戶端,如果沒有做目的地址轉換的話,此處將找不到任何用戶端,最終資料將發往虛擬網卡,等待核心標準路由系統的路由,很可能就發往預設閘道了
mi = multi_get_instance_by_virtual_addr (m, &dest, true);
if (mi) {
multi_unicast (m, &c->c2.to_tun, mi); //向目的地址單播
register_activity (c, BLEN(&c->c2.to_tun));
c->c2.to_tun.len = 0;
}
}
}
} else if (TUNNEL_TYPE (m->top.c1.tuntap) == DEV_TYPE_TAP) {
mroute_flags = mroute_extract_addr_from_packet (&src, //從乙太網路資料幀中解析出源/目的mac地址
&dest,
NULL,
NULL,
&c->c2.to_tun,
DEV_TYPE_TAP);
if (multi_learn_addr (m, m->pending, &src, 0) == m->pending) {
if (m->enable_c2c) { //以下是廣播/多播情況,比如tap模式下的arp就是廣播,可以看出mroute_extract_addr_ether處理了arp,設定了多播標誌,OpenVPN中,多播和廣播統一處理
if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST)) {
multi_bcast (m, &c->c2.to_tun, m->pending, NULL);
} else { //下面根據目的mac來判斷目的地是否是同一個虛擬子網的,如果是,則將以太幀發過去
mi = multi_get_instance_by_virtual_addr (m, &dest, false);
if (mi){
multi_unicast (m, &c->c2.to_tun, mi); //單播發送以太幀
register_activity (c, BLEN(&c->c2.to_tun));
c->c2.to_tun.len = 0; //不再寫入虛擬網卡
}
}
}
...
} else {
c->c2.to_tun.len = 0;
}
}
}
//所有其它情況都將受到的資料包寫入虛擬網卡中,一旦寫入虛擬網卡以後,資料包的流向就不再受OpenVPN的控制了,而是完全受核心路由表的控制
ret = multi_process_post (m, m->pending, mpp_flags);
...
}
在multi_process_incoming_tun中有下面一個判斷:
multi_set_pending (m, multi_get_instance_by_virtual_addr (m, &dest, dev_type == DEV_TYPE_TUN));
if (m->pending) --->後續處理
這是判斷目的地址的有效性,作為OpenVPN伺服器來講,從虛擬網卡中來的資料包就是要發往OpenVPN用戶端的資料包,因此需要判斷目的地址,和multi_process_incoming_link的判斷相反。
結論是:tun模式按照ip地址路由,tap模式按照mac地址路由。在用戶端,沒有伺服器端這麼複雜的判斷,只是經過“in-tun--out-link-加密,in-link--out-tun-解密”的過程即可

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.