我的机器设置了正在运行的VPN客户端,并希望通过VPN隧道连接到Internet上的主机,或者通过在套接字上指定绑定地址直接通过本地接口连接。请考虑以下代码示例:
import socket, subprocess, re
def get_ipv4_address():
ifc_resp = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE).communicate()
patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
return patt.findall(ifc_resp[0])
def check_sock(addr):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((addr, 0))
s.connect(("www.google.com", 80))
s.close()
def main():
addrs = sorted(a for a in get_ipv4_address() if not a.startswith("127.0."))
print "Checking addresses " + ", ".join(addrs)
for addr in addrs:
print "Connecting via " + addr
check_sock(addr)
main()
当我运行它时,可以通过VPN IP地址设置连接而不会出现问题。虽然程序在连接上连接到本地网络时挂起:
>>> python binddemo.py
Checking addresses 10.200.195.233, 192.168.2.33
Connecting via 10.200.195.233
Connecting via 192.168.2.33
^CTraceback (most recent call last):
File "binddemo.py", line 22, in <module>
main()
File "binddemo.py", line 20, in main
check_sock(addr)
File "binddemo.py", line 12, in check_sock
s.connect(("www.google.com", 80))
File "/usr/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
KeyboardInterrupt
我不明白为什么会发生这种情况,因为本地网卡仍然应该正确设置路由以接触互联网:
>>> ip route
default via 10.200.195.1 dev tun0 proto static metric 50
default via 192.168.2.1 dev wlan0 proto static metric 600
10.200.195.0/24 dev tun0 proto kernel scope link src 10.200.195.233 metric 50
62.113.253.4 via 192.168.2.1 dev wlan0 proto static metric 600
169.254.0.0/16 dev wlan0 scope link metric 1000
192.168.2.0/24 dev wlan0 proto kernel scope link src 192.168.2.33 metric 600
指定到普通IP地址(而不是谷歌主机)的连接同样失败,所以我认为这不是DNS查找造成麻烦。任何想法如何解决或至少进一步调查?
答案 0 :(得分:1)
在不会bind()
的客户端套接字上使用listen()
没有做任何事情。用于传出连接的接口完全取决于您的路由配置。
您已设置两个默认网关,但进入您的wlan界面的网关比您的隧道设备具有更高的metric
。所以linux总是将tuneling接口用作默认网关。
以下是一个更好,更深入的解释:https://serverfault.com/questions/648276/routing-selection-specificity-vs-metric
[编辑1]
在更仔细地查看路由表之后,删除隧道设备的默认网关应该可以解决您的问题,因为您还有一个网络路由设置,可以正确地将所有流量路由到您的VPN。所以尝试删除这个:
default via 10.200.195.1 dev tun0 proto static metric 50
因为这个会将您的vpn流量路由到tun0
:
10.200.195.0/24 dev tun0 proto kernel scope link src 10.200.195.233 metric 50
[编辑2]
如果您想通过隧道设备保留默认路由,可以使用network namespaces
:https://superuser.com/questions/241178/how-to-use-different-network-interfaces-for-different-processes/750412#750412
但您仍然无法从单个程序访问这两个网络。
答案 1 :(得分:0)
最终解决了什么:
echo "1 localwlan" >> /etc/iproute2/rt_tables
ip route add default table localwlan via 192.168.2.33 dev wlan0
ip rule add from 192.168.2.33 lookup localwlan
感谢@Christian Eichelman指出我正确的方向