
這可能是個相當新手的問題,但是......
我使用的是 Ubuntu 18.04.3 LTS,我有一個VPN我想將其用於一些應用程式。我結帳了namespaced-openvpn
它有效!需要注意的是,我無法在本地連接到該應用程式(出於管理目的)。
有沒有辦法將 VPN 隧道內的某個連接埠轉送到本機沒有 VPN 隧道將其用於任何其他目的並因此洩露太多資訊?
我已經能夠做到的事情:
- 跑步
namespaced-openvpn
-腳本:sudo ./namespaced-openvpn --namespace vpn --config /etc/openvpn/vpn-xxxxx.ovpn
- 在網路命名空間內執行應用程式:
sudo ip netns exec vpn application
我想要實現的目標:
1234
連接到從真實本地主機(enp3s0
乙太網路適配器)在 VPN 隧道(例如連接埠)內啟動的應用程式- 以某種方式轉發此端口,使我能夠從 LAN 中的其他計算機訪問它
答案1
晚了很多年,但萬一有人遇到這個問題,就像我希望我在過去幾天左右所做的那樣。
希望它能幫助某人。
首先,這是namespaced-vpn,它完成了讓一切運作的90% 的工作。
https://github.com/slingamn/namespaced-openvpn
這是一個幾乎與此一模一樣的問題的答案,儘管我不明白正在做什麼以及為什麼要做這些事情,但它對我幫助很大。 https://unix.stackexchange.com/questions/391193/how-to-forward-traffic- Between-linux-network-namespaces
我將嘗試使用我在搜尋中找到的零碎資訊來解釋經過大量嘗試和錯誤後我所理解的內容。
我認為,將連線轉發到您的服務(不是從運行該服務的 PC)最相關的部分是(請注意 PREROUTING 後面的感嘆號):
iptables -t nat -A PREROUTING ! -s 10.0.0.0/24 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
其中,10.0.0.0/24
表示分配了您不想轉送的 IP 範圍。
這主要是為了防止路由循環,即使用10.0.0.0/24
子網路存取的任何服務都會路由回其自身。
--dport 80 僅轉送尋求連接埠 80 IE 網路伺服器連線的封包。
10.0.0.2
是已移至伺服器正在運作的命名空間內的 veth 介面。
這使得10.0.0.0/24
正在尋求連接埠 80 服務的封包(而不是來自子網路)將其目標 IP 轉換為10.0.0.2
.範例:192.168.1.200:80
becomes10.0.0.2:80
可能是您的伺服器所在的命名空間內的介面。
我在多個命名空間中啟動並運行多個 VPN 隧道。如果我不將 PREROUTING 規則新增至我的 iptables,我將無法從 LAN 上的 PC 外部存取資源。
如果您希望從自己的 PC 上存取它,則必須添加以下規則:
iptables --table nat --append OUTPUT --destination 192.168.1.2 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.0.0.2
因此,如果您在伺服器所在的 PC 上的瀏覽器中鍵入內容192.168.1.2
以存取您的伺服器,它將被路由到10.0.0.2
。
我將嘗試解釋我的設置的一部分......
命名空間範例:ip netns add ns_example
建立 veth 對。一側將留在根/普通命名空間(我稱之為host
),另一側將進入帶有 VPN 的命名空間。
ip link add dev ihost type veth peer name ivpn
將 veth 對的 vpn 端移至目標命名空間:
ip link set dev ivpn netns ns_example
將 ips 指派給您建立的 veth 對。
我使用 /32 是因為我只想分配這個確切的 IP,而不是範圍。否則,當我啟動設備時,一些路由會自動插入到我的ip route
表中,這會擾亂我的其他命名空間的路由。
分配給主機端。
ip addr add 10.0.0.1/32 dev ihost
若要指派給已移至命名空間的 vpn 端,您必須在命令前面加上 ..
ip netns exec TARGET_NAMESPACE
因此,將 ip 指派給 vpn 端:
ip netns exec ns_example ip addr add 10.0.0.2/32 dev ivpn
現在調出介面。
ip link set dev ihost up
ip netns exec ns_example ip link set dev ivpn up
這裡我添加了路由和 iptables 以使流量在它們之間流動。
從根命名空間,要到達 VPN 端 ( 10.0.0.2
),請使用介面 ihost 並將來源位址重寫到根命名空間端 ( 10.0.0.1
)。
ip route add 10.0.0.2/32 dev ihost src 10.0.0.1
在 VPN 命名空間內從相反的角度做完全相同的事情。
ip netns exec ns_example ip route add 10.0.0.1/32 dev ivpn src 10.0.0.2
現在,我添加了相同的操作,iptables
這些操作是獨立的ip route
但完成類似的任務。
任何資料包10.0.0.2
的來源位址都會重寫為10.0.0.1
iptables --table nat --append POSTROUTING --destination 10.0.0.2/32 --jump SNAT --to-source 10.0.0.1
完全相同的事情,但是相反的視角和內部命名空間。
ip netns exec ns_example iptables --table nat --append POSTROUTING --destination 10.0.0.1/32 --jump SNAT --to-source 10.0.0.2
如果我理解正確的話,來源位址重寫只是為了確保資料包知道如何返回命名空間,反之亦然。
現在,例如:要存取連接埠 8080 上的命名空間中的 torrent webui,我會這樣做。
任何發送至我的 LAN IP 的封包(例如:我192.168.1.2:8080
在瀏覽器中輸入)。它將重寫目標到我的 torrent 用戶端正在運行的命名空間(例如10.0.0.2
:)。
iptables --table nat --append OUTPUT --destination 192.168.1.2/32 --protocol tcp --match tcp --dport 8080 --jump DNAT --to-destination 10.0.0.2
該規則專門僅轉送連接埠 8080,並且該規則供您在執行該服務的 PC 上存取該服務。網路存取上的任何其他 PC 都192.168.1.2:8080
需要我在答案頂部提到的 PREROUTING 規則(只需將 --dport 80 更改為 --dport 8080 或您需要的任何連接埠/協定)。
對於使用此方法和 namespaced-vpn.py 腳本的人。如果您必須重設 VPN,則可能會遇到問題。當命名空間 VPN 偵測到目標命名空間內除環回介面之外的介面時,它會引發異常lo
。
這是當我使用 namespaced-vpn.py 時,當我的目標命名空間已經存在並且它有我的 veth 對時,會拋出異常的部分。
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
if adapters != [b'lo']:
LOG.error('Namespace %s already has adapters %s, exiting.' % (namespace, adapters))
raise Exception
這是我使用過的範例修改。
allowed_adapters = [b'lo', b'ivpn']
if os.path.exists(os.path.join('/var/run/netns', namespace)):
adapters = _adapter_names(namespace)
# Iterate and ensure all are in allowed list
for a in adapters:
if not a.split(b'@')[0] in allowed_adapters:
LOG.error('Namespace %s has non-whitelisted adapters %s, exiting.' % (namespace, adapters))
raise Exception
只需確保為您期望已存在於「def setup_namespace(namespace)」函數底部的每個介面新增這樣的呼叫即可。將 LO 替換為設備名稱
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'LO', 'up'])
例子:
subprocess.check_call(_enter_namespace_cmd(namespace) + [IP_CMD, 'link', 'set', 'ivpn', 'up'])
對於執行連接到 VPN 介面的 BitTorrent 用戶端的人來說,您可能會遇到用戶端因某種原因隨機停止連線的問題。例如,您早上醒來發現所有漂亮的下載內容在您離開後 10 分鐘就被凍結了。
我相信這個問題是由於 vpn 軟體 IE openvpn 引起的,無論出於何種原因(錯誤、ping 重新啟動等)重新連接到 vpn 提供者並被分配了新的 IP 位址。 VPN 介面可能需要瞬間離線才能重置配置,這會導致客戶端發生故障(qBittorrent 肯定會這樣做)。我開始研究的一個「修復」是編寫一個腳本來偵測 vpn 介面何時收到新的 IP 位址或因任何原因離線。該腳本應該優雅地(重要:優雅地避免損壞某些內容/檔案系統錯誤)退出 torrent 用戶端,然後重新啟動它。我還沒有工作腳本,但這似乎是解決這個問題的一個不錯的載體。
答案2
好的。看來這個問題太複雜了,沒有人真正回答,或者可能以前已經回答過,但沒人願意回答。
無論如何:我又研究了一天,並發現由於我只對為應用程式的 Web 介面公開一個連接埠感興趣,所以我也可以使用socat
。所以我做了。
建立命名空間-openvpn 連線並在該網路命名空間內啟動應用程式後,我在專用終端機中執行以下命令:
sudo socat tcp-listen:PORT-TO-FORWARD-TO,fork,reuseaddr exec:'ip netns exec vpn socat STDIO tcp-connect\:127.0.0.1\:PORT-TO-LISTEN-TO',nofork
筆記:
PORT-TO-FORWARD-TO
是我想要將連接埠轉送到的連接埠(在根網路命名空間)PORT-TO-LISTEN-TO
是應用程式的端口,我想將其公開到根命名空間中127.0.0.1
我必須使用實際的本地主機IP(不是localhost
名稱,因為它似乎沒有正確解析):
確保轉義單引號內的雙點字元 ( )- 我不確定這是否會導致 DNS 洩漏;據我檢查,它沒有,但我不能確定,因為我不知道如何測試它
還剩下要做的事:
- 自動化所有命令以啟動應用程式並在啟動時轉發連接埠:我目前不需要這個,但是如果/當我找到如何做到這一點時,我將在此處添加它