mirror of
https://github.com/KusakabeShi/EtherGuard-VPN.git
synced 2024-11-21 23:03:08 +01:00
bugfix: addpeer API. new: tcpsock,udpsock,fd
This commit is contained in:
parent
b99b0254ea
commit
776df87879
28
README.md
28
README.md
@ -7,14 +7,14 @@ A Full Mesh Layer2 VPN based on wireguard-go
|
|||||||
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
|
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
|
||||||
|
|
||||||
OSPF can find best route based on it's cost.
|
OSPF can find best route based on it's cost.
|
||||||
But sometimes the lentancy are different in the packet goes and back.
|
But sometimes the latency are different in the packet goes and back.
|
||||||
I'am thinking, is it possible to find the best route based on the **single-way latency**?
|
I'm thinking, is it possible to find the best route based on the **single-way latency**?
|
||||||
For example, I have two routes A and B at node N1, both of them can reach my node N2. A goes fast, but B backs fast.
|
For example, I have two routes A and B at node N1, both of them can reach my node N2. A goes fast, but B backs fast.
|
||||||
My VPN can automatically send packet through route A at node N1, and the packet backs from route B.
|
My VPN can automatically send packet through route A at node N1, and the packet backs from route B.
|
||||||
|
|
||||||
Here is the solution. This VPN `Etherguard` can collect all the single-way lentancy from all nodes, and calculate the best route using [Floyd–Warshall algorithm](https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm).
|
Here is the solution. This VPN `Etherguard` can collect all the single-way latency from all nodes, and calculate the best route using [Floyd–Warshall algorithm](https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm).
|
||||||
|
|
||||||
Wirried about the clock not match so that the measure result are not correct? It doesn't matter, here is the proof (Mandarin): [https://www.kskb.eu.org/2021/08/rootless-routerpart-3-etherguard.html](https://www.kskb.eu.org/2021/08/rootless-routerpart-3-etherguard.html)
|
Worried about the clock not match so that the measure result are not correct? It doesn't matter, here is the proof (Mandarin): [https://www.kskb.eu.org/2021/08/rootless-routerpart-3-etherguard.html](https://www.kskb.eu.org/2021/08/rootless-routerpart-3-etherguard.html)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ Usage of ./etherguard-go:
|
|||||||
|
|
||||||
## Mode
|
## Mode
|
||||||
|
|
||||||
1. Static Mode: Similar to origional wireguard. [Introduction](example_config/static_mode/README.md).
|
1. Static Mode: Similar to original wireguard. [Introduction](example_config/static_mode/README.md).
|
||||||
2. Super Mode: Inspired by[n2n](https://github.com/ntop/n2n). [Introduction](example_config/super_mode/README.md).
|
2. Super Mode: Inspired by[n2n](https://github.com/ntop/n2n). [Introduction](example_config/super_mode/README.md).
|
||||||
3. P2P Mode: Inspired by[tinc](https://github.com/gsliepen/tinc). [Introduction](example_config/p2p_mode/README.md).
|
3. P2P Mode: Inspired by[tinc](https://github.com/gsliepen/tinc). [Introduction](example_config/p2p_mode/README.md).
|
||||||
|
|
||||||
@ -53,8 +53,14 @@ Usage of ./etherguard-go:
|
|||||||
1. `dummy`: Dymmy interface, drop any packet received. You need this if you want to setup it as a relay node.
|
1. `dummy`: Dymmy interface, drop any packet received. You need this if you want to setup it as a relay node.
|
||||||
2. `stdio`: Wrtie to stdout,read from stdin.
|
2. `stdio`: Wrtie to stdout,read from stdin.
|
||||||
Paramaters: `macaddrprefix`,`l2headermode`
|
Paramaters: `macaddrprefix`,`l2headermode`
|
||||||
3. `udpsock`: Write to an udp socket, and read from an net assress.
|
3. `udpsock`: Read/Write the raw packet to an udp socket.
|
||||||
Paramaters: `macaddrprefix`,`recvaddr`,`sendaddr`
|
Paramaters: `recvaddr`,`sendaddr`
|
||||||
|
3. `tcpsock`: Read/Write the raw packet to a tcp socket.
|
||||||
|
Paramaters: `recvaddr`,`sendaddr`
|
||||||
|
3. `unixsock`: Read/Write the raw packet to an unix socket.
|
||||||
|
Paramaters: `recvaddr`,`sendaddr`
|
||||||
|
3. `fd`: Read/Write the raw packet to specific file descriptor.
|
||||||
|
Paramaters: None. But require environment variable `EG_FD_RX` and `EG_FD_TX`
|
||||||
4. `vpp`: Integrate to VPP by libmemif.
|
4. `vpp`: Integrate to VPP by libmemif.
|
||||||
Paramaters: `name`,`vppifaceid`,`vppbridgeid`,`macaddrprefix`,`mtu`
|
Paramaters: `name`,`vppifaceid`,`vppbridgeid`,`macaddrprefix`,`mtu`
|
||||||
5. `tap`: Read/Write to tap device from linux.
|
5. `tap`: Read/Write to tap device from linux.
|
||||||
@ -65,9 +71,9 @@ Usage of ./etherguard-go:
|
|||||||
5. `macaddrprefix`: Mac address Prefix.
|
5. `macaddrprefix`: Mac address Prefix.
|
||||||
Real Mac address=[Prefix]:[NodeID].
|
Real Mac address=[Prefix]:[NodeID].
|
||||||
If you fill full mac address here, NodeID will be ignored.
|
If you fill full mac address here, NodeID will be ignored.
|
||||||
6. `recvaddr`: Listen address for `udpsock` mode
|
6. `recvaddr`: Listen address for `XXXsock` mode(server mode)
|
||||||
7. `sendaddr`: Packet send address for `udpsock` mode
|
7. `sendaddr`: Packet send address for `XXXsock` mode(client mode)
|
||||||
8. `l2headermode`: For debug usage, `stdio` and `udpsock` mode only
|
8. `l2headermode`: For debug usage, for `stdio` mode only
|
||||||
1. `nochg`: Do not change anything.
|
1. `nochg`: Do not change anything.
|
||||||
2. `kbdbg`: Keyboard debug mode.
|
2. `kbdbg`: Keyboard debug mode.
|
||||||
Let me construct Layer 2 header by ascii character only.
|
Let me construct Layer 2 header by ascii character only.
|
||||||
@ -137,7 +143,7 @@ make
|
|||||||
Build Etherguard with VPP integrated.
|
Build Etherguard with VPP integrated.
|
||||||
You need libmemif.so installed to run this version.
|
You need libmemif.so installed to run this version.
|
||||||
|
|
||||||
Install VPP and libemif
|
Install VPP and libmemif
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "deb [trusted=yes] https://packagecloud.io/fdio/release/ubuntu focal main" > /etc/apt/sources.list.d/99fd.io.list
|
echo "deb [trusted=yes] https://packagecloud.io/fdio/release/ubuntu focal main" > /etc/apt/sources.list.d/99fd.io.list
|
||||||
|
16
README_zh.md
16
README_zh.md
@ -59,8 +59,14 @@ Usage of ./etherguard-go-vpp:
|
|||||||
1. `dummy`: 收到的封包直接丟棄,也不發出任何封包。作為中繼節點使用
|
1. `dummy`: 收到的封包直接丟棄,也不發出任何封包。作為中繼節點使用
|
||||||
2. `stdio`: 收到的封包丟stdout,stdin進來的資料丟入vpn網路
|
2. `stdio`: 收到的封包丟stdout,stdin進來的資料丟入vpn網路
|
||||||
需要參數: `macaddrprefix`,`l2headermode`
|
需要參數: `macaddrprefix`,`l2headermode`
|
||||||
3. `udpsock`: 收到的封包用udp丟到某個網路位置,監聽port進來的資料丟去vpn網路
|
3. `udpsock`: 把VPN網路收到的layer2封包讀寫去一個udp socket.
|
||||||
需要參數: `macaddrprefix`,`recvaddr`,`sendaddr`
|
Paramaters: `recvaddr`,`sendaddr`
|
||||||
|
3. `tcpsock`: 把VPN網路收到的layer2封包讀寫去一個tcp socket.
|
||||||
|
Paramaters: `recvaddr`,`sendaddr`
|
||||||
|
3. `unixsock`: 把VPN網路收到的layer2封包讀寫去一個unix socket.
|
||||||
|
Paramaters: `recvaddr`,`sendaddr`
|
||||||
|
3. `fd`: 把VPN網路收到的layer2封包讀寫去一個特定的file descriptor.
|
||||||
|
Paramaters: 無. 但是使用環境變數 `EG_FD_RX` 和 `EG_FD_TX` 來指定
|
||||||
4. `vpp`: 使用libmemif使vpp加入VPN網路
|
4. `vpp`: 使用libmemif使vpp加入VPN網路
|
||||||
需要參數: `name`,`vppifaceid`,`vppbridgeid`,`macaddrprefix`,`mtu`
|
需要參數: `name`,`vppifaceid`,`vppbridgeid`,`macaddrprefix`,`mtu`
|
||||||
5. `tap`: Linux的tap設備。讓linux加入VPN網路
|
5. `tap`: Linux的tap設備。讓linux加入VPN網路
|
||||||
@ -70,9 +76,9 @@ Usage of ./etherguard-go-vpp:
|
|||||||
4. `vppbridgeid`: VPP 的網橋ID。不使用VPP網橋功能的話填0
|
4. `vppbridgeid`: VPP 的網橋ID。不使用VPP網橋功能的話填0
|
||||||
5. `macaddrprefix`: MAC地址前綴。真正的 MAC 地址=[前綴]:[NodeID]。
|
5. `macaddrprefix`: MAC地址前綴。真正的 MAC 地址=[前綴]:[NodeID]。
|
||||||
如果這邊填了完整6格長度,就忽略`NodeID`
|
如果這邊填了完整6格長度,就忽略`NodeID`
|
||||||
6. `recvaddr`: 僅限`udpsock`生效。收到的東西丟去 VPN 網路
|
6. `recvaddr`: 僅限`XXXsock`生效。listen地址,收到的東西丟去 VPN 網路
|
||||||
7. `sendaddr`: 僅限`udpsock`生效。VPN網路收到的東西丟去這個 udp 地址
|
7. `sendaddr`: 僅限`XXXsock`生效。連線地址,VPN網路收到的東西丟去這個地址
|
||||||
8. `l2headermode`: 僅限 `stdio` 和 `udpsock` 生效。debug用途,有三種模式:
|
8. `l2headermode`: 僅限 `stdio` 生效。debug用途,有三種模式:
|
||||||
1. `nochg`: 從 VPN 網路收到什麼,就往tap裝置發送什麼。不對封包作任何更動
|
1. `nochg`: 從 VPN 網路收到什麼,就往tap裝置發送什麼。不對封包作任何更動
|
||||||
2. `kbdbg`: 鍵盤bebug模式。搭配 `stdio` 模式,讓我 debug 用
|
2. `kbdbg`: 鍵盤bebug模式。搭配 `stdio` 模式,讓我 debug 用
|
||||||
因為前 12 byte 會用來做選路判斷,但是只是要debug,構造完整的封包就不是很方便
|
因為前 12 byte 會用來做選路判斷,但是只是要debug,構造完整的封包就不是很方便
|
||||||
|
@ -463,6 +463,7 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
|||||||
dst_nodeID = EgHeader.GetDst()
|
dst_nodeID = EgHeader.GetDst()
|
||||||
elem.packet = elem.packet[:EgHeader.GetPacketLength()+path.EgHeaderLen] // EG header + true packet
|
elem.packet = elem.packet[:EgHeader.GetPacketLength()+path.EgHeaderLen] // EG header + true packet
|
||||||
packet_type = elem.Type
|
packet_type = elem.Type
|
||||||
|
peer.LastPingReceived = time.Now()
|
||||||
|
|
||||||
if device.IsSuperNode {
|
if device.IsSuperNode {
|
||||||
peer.LastPingReceived = time.Now()
|
peer.LastPingReceived = time.Now()
|
||||||
|
@ -318,9 +318,9 @@ func (device *Device) server_process_Pong(peer *Peer, content path.PongMsg) erro
|
|||||||
|
|
||||||
func (device *Device) process_ping(peer *Peer, content path.PingMsg) error {
|
func (device *Device) process_ping(peer *Peer, content path.PingMsg) error {
|
||||||
peer.LastPingReceived = time.Now()
|
peer.LastPingReceived = time.Now()
|
||||||
peer.Lock()
|
//peer.Lock()
|
||||||
//remove peer.endpoint_trylist
|
//remove peer.endpoint_trylist
|
||||||
peer.Unlock()
|
//peer.Unlock()
|
||||||
PongMSG := path.PongMsg{
|
PongMSG := path.PongMsg{
|
||||||
Src_nodeID: content.Src_nodeID,
|
Src_nodeID: content.Src_nodeID,
|
||||||
Dst_nodeID: device.ID,
|
Dst_nodeID: device.ID,
|
||||||
@ -479,7 +479,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, content path.UpdatePeerM
|
|||||||
//Peer died, try to switch to this new endpoint
|
//Peer died, try to switch to this new endpoint
|
||||||
for url, _ := range peerinfo.Connurl {
|
for url, _ := range peerinfo.Connurl {
|
||||||
thepeer.Lock()
|
thepeer.Lock()
|
||||||
thepeer.endpoint_trylist.Set(url, time.Time{}) //another gorouting will process it
|
thepeer.endpoint_trylist.LoadOrStore(url, time.Time{}) //another gorouting will process it
|
||||||
thepeer.Unlock()
|
thepeer.Unlock()
|
||||||
send_signal = true
|
send_signal = true
|
||||||
}
|
}
|
||||||
@ -625,7 +625,7 @@ func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.Boardcas
|
|||||||
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.PeerAliveTimeout)).Before(time.Now()) {
|
if thepeer.LastPingReceived.Add(path.S2TD(device.DRoute.PeerAliveTimeout)).Before(time.Now()) {
|
||||||
//Peer died, try to switch to this new endpoint
|
//Peer died, try to switch to this new endpoint
|
||||||
thepeer.Lock()
|
thepeer.Lock()
|
||||||
thepeer.endpoint_trylist.Set(content.ConnURL, time.Time{}) //another gorouting will process it
|
thepeer.endpoint_trylist.LoadOrStore(content.ConnURL, time.Time{}) //another gorouting will process it
|
||||||
thepeer.Unlock()
|
thepeer.Unlock()
|
||||||
device.event_tryendpoint <- struct{}{}
|
device.event_tryendpoint <- struct{}{}
|
||||||
}
|
}
|
||||||
|
71
example_config/super_mode/n1_fd.yaml
Normal file
71
example_config/super_mode/n1_fd.yaml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
interface:
|
||||||
|
itype: fd
|
||||||
|
name: tap1
|
||||||
|
vppifaceid: 1
|
||||||
|
vppbridgeid: 4242
|
||||||
|
macaddrprefix: AA:BB:CC:DD
|
||||||
|
mtu: 1416
|
||||||
|
recvaddr: 127.0.0.1:4001
|
||||||
|
sendaddr: 127.0.0.1:5001
|
||||||
|
l2headermode: kbdbg
|
||||||
|
nodeid: 1
|
||||||
|
nodename: Node01
|
||||||
|
defaultttl: 200
|
||||||
|
l2fibtimeout: 3600
|
||||||
|
privkey: 6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=
|
||||||
|
listenport: 3001
|
||||||
|
loglevel:
|
||||||
|
loglevel: normal
|
||||||
|
logtransit: true
|
||||||
|
logcontrol: true
|
||||||
|
lognormal: true
|
||||||
|
logntp: true
|
||||||
|
dynamicroute:
|
||||||
|
sendpinginterval: 16
|
||||||
|
peeralivetimeout: 30
|
||||||
|
dupchecktimeout: 40
|
||||||
|
conntimeout: 30
|
||||||
|
connnexttry: 5
|
||||||
|
savenewpeers: true
|
||||||
|
supernode:
|
||||||
|
usesupernode: true
|
||||||
|
pskey: 'iPM8FXfnHVzwjguZHRW9bLNY+h7+B1O2oTJtktptQkI='
|
||||||
|
connurlv4: 127.0.0.1:3000
|
||||||
|
pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=
|
||||||
|
connurlv6: ''
|
||||||
|
pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=
|
||||||
|
apiurl: http://127.0.0.1:3000/api
|
||||||
|
supernodeinfotimeout: 50
|
||||||
|
p2p:
|
||||||
|
usep2p: false
|
||||||
|
sendpeerinterval: 20
|
||||||
|
graphrecalculatesetting:
|
||||||
|
staticmode: false
|
||||||
|
jittertolerance: 20
|
||||||
|
jittertolerancemultiplier: 1.1
|
||||||
|
nodereporttimeout: 40
|
||||||
|
recalculatecooldown: 5
|
||||||
|
ntpconfig:
|
||||||
|
usentp: true
|
||||||
|
maxserveruse: 8
|
||||||
|
synctimeinterval: 3600
|
||||||
|
ntptimeout: 3
|
||||||
|
servers:
|
||||||
|
- time.google.com
|
||||||
|
- time1.google.com
|
||||||
|
- time2.google.com
|
||||||
|
- time3.google.com
|
||||||
|
- time4.google.com
|
||||||
|
- time1.facebook.com
|
||||||
|
- time2.facebook.com
|
||||||
|
- time3.facebook.com
|
||||||
|
- time4.facebook.com
|
||||||
|
- time5.facebook.com
|
||||||
|
- time.cloudflare.com
|
||||||
|
- time.apple.com
|
||||||
|
- time.asia.apple.com
|
||||||
|
- time.euro.apple.com
|
||||||
|
- time.windows.com
|
||||||
|
nexthoptable: {}
|
||||||
|
resetconninterval: 86400
|
||||||
|
peers: []
|
61
example_config/super_mode/n1_test_fd_mode.py
Normal file
61
example_config/super_mode/n1_test_fd_mode.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
pr, ew = os.pipe()
|
||||||
|
er, pw = os.pipe()
|
||||||
|
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
bufsize=1500
|
||||||
|
|
||||||
|
def signal_handler(sig, frame):
|
||||||
|
print('You pressed Ctrl+C!')
|
||||||
|
os.close(pr)
|
||||||
|
os.close(pw)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def read_loop(fd):
|
||||||
|
print("Main Start read fd:",fd)
|
||||||
|
with os.fdopen(fd, 'rb') as fdfile:
|
||||||
|
while True:
|
||||||
|
text = fdfile.read()
|
||||||
|
if len(text) == 0:
|
||||||
|
print("EOF!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||||
|
break
|
||||||
|
print("Main: RECEIVED:",text)
|
||||||
|
|
||||||
|
def write_loop(fd):
|
||||||
|
with os.fdopen(fd, 'wb') as fdfile:
|
||||||
|
while True:
|
||||||
|
print("Main Write fd:",fd)
|
||||||
|
text = b'\xff\xff\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xaa\xaa' + b'm'*88
|
||||||
|
fdfile.write(text)
|
||||||
|
fdfile.flush()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
tr = threading.Thread(target = read_loop, args=(pr,))
|
||||||
|
tr.start()
|
||||||
|
|
||||||
|
tw = threading.Thread(target = write_loop, args=(pw,))
|
||||||
|
tw.start()
|
||||||
|
|
||||||
|
os.environ["EG_FD_RX"] = str(er)
|
||||||
|
os.environ["EG_FD_TX"] = str(ew)
|
||||||
|
|
||||||
|
print(str(er), str(ew))
|
||||||
|
|
||||||
|
#p = subprocess.Popen('./etherguard-go -config example_config/super_mode/n1.yaml -mode edge'.split(" "),pass_fds=[er,ew])
|
||||||
|
p = subprocess.Popen('python3 example_config/super_mode/n1_test_fd_mode2.py'.split(" "),pass_fds=[er,ew])
|
||||||
|
os.close(er)
|
||||||
|
os.close(ew)
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.pause()
|
||||||
|
|
||||||
|
# tr.join()
|
||||||
|
# tw.join()
|
||||||
|
# os.close(pr)
|
||||||
|
# os.close(pw)
|
51
example_config/super_mode/n1_test_fd_mode2.py
Normal file
51
example_config/super_mode/n1_test_fd_mode2.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
er = int( os.environ['EG_FD_RX'])
|
||||||
|
ew = int( os.environ['EG_FD_TX'])
|
||||||
|
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
bufsize=1500
|
||||||
|
|
||||||
|
def signal_handler(sig, frame):
|
||||||
|
print('You pressed Ctrl+C!')
|
||||||
|
os.close(er)
|
||||||
|
os.close(ew)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def read_loop(fd):
|
||||||
|
print("Sub: Start read fd:",fd)
|
||||||
|
with os.fdopen(fd, 'rb') as fdfile:
|
||||||
|
while True:
|
||||||
|
text = fdfile.read()
|
||||||
|
if len(text) == 0:
|
||||||
|
print("EOF!!!!!!!!!!!!!!!!!!!!!!!!")
|
||||||
|
break
|
||||||
|
print("Sub RECEIVED:",text)
|
||||||
|
|
||||||
|
def write_loop(fd):
|
||||||
|
with os.fdopen(fd, 'wb') as fdfile:
|
||||||
|
while True:
|
||||||
|
print("Sub: Write fd:",fd)
|
||||||
|
text = b'\xff\xff\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xaa\xaa' + b's'*88
|
||||||
|
fdfile.write(text)
|
||||||
|
fdfile.flush()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
tr = threading.Thread(target = read_loop, args=(er,))
|
||||||
|
tr.start()
|
||||||
|
|
||||||
|
tw = threading.Thread(target = write_loop, args=(ew,))
|
||||||
|
tw.start()
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
signal.pause()
|
||||||
|
|
||||||
|
# tr.join()
|
||||||
|
# tw.join()
|
||||||
|
# os.close(er)
|
||||||
|
# os.close(ew)
|
@ -25,6 +25,7 @@ nexthoptable:
|
|||||||
2:
|
2:
|
||||||
1: 1
|
1: 1
|
||||||
edgetemplate: example_config/super_mode/n1.yaml
|
edgetemplate: example_config/super_mode/n1.yaml
|
||||||
|
usepskforinteredge: true
|
||||||
peers:
|
peers:
|
||||||
- nodeid: 1
|
- nodeid: 1
|
||||||
name: Node_01
|
name: Node_01
|
||||||
|
11
main_edge.go
11
main_edge.go
@ -10,7 +10,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -190,9 +189,13 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) (
|
|||||||
case "stdio":
|
case "stdio":
|
||||||
thetap, err = tap.CreateStdIOTAP(econfig.Interface, econfig.NodeID)
|
thetap, err = tap.CreateStdIOTAP(econfig.Interface, econfig.NodeID)
|
||||||
case "udpsock":
|
case "udpsock":
|
||||||
lis, _ := net.ResolveUDPAddr("udp", econfig.Interface.RecvAddr)
|
thetap, err = tap.CreateUDPSockTAP(econfig.Interface, econfig.NodeID)
|
||||||
sen, _ := net.ResolveUDPAddr("udp", econfig.Interface.SendAddr)
|
case "tcpsock":
|
||||||
thetap, err = tap.CreateUDPSockTAP(econfig.Interface, econfig.NodeID, lis, sen)
|
thetap, err = tap.CreateSockTAP(econfig.Interface, "tcp", econfig.NodeID)
|
||||||
|
case "unixsock":
|
||||||
|
thetap, err = tap.CreateSockTAP(econfig.Interface, "unix", econfig.NodeID)
|
||||||
|
case "fd":
|
||||||
|
thetap, err = tap.CreateFdTAP(econfig.Interface, econfig.NodeID)
|
||||||
case "vpp":
|
case "vpp":
|
||||||
thetap, err = tap.CreateVppTAP(econfig.Interface, econfig.NodeID, econfig.LogLevel.LogLevel)
|
thetap, err = tap.CreateVppTAP(econfig.Interface, econfig.NodeID, econfig.LogLevel.LogLevel)
|
||||||
case "tap":
|
case "tap":
|
||||||
|
@ -32,15 +32,15 @@ var (
|
|||||||
http_NhTableStr []byte
|
http_NhTableStr []byte
|
||||||
http_PeerInfo config.API_Peers
|
http_PeerInfo config.API_Peers
|
||||||
|
|
||||||
http_PeerID2PubKey map[config.Vertex]string
|
|
||||||
|
|
||||||
http_passwords config.Passwords
|
http_passwords config.Passwords
|
||||||
http_StateExpire time.Time
|
http_StateExpire time.Time
|
||||||
http_StateString_tmp []byte
|
http_StateString_tmp []byte
|
||||||
|
|
||||||
|
http_maps_lock sync.RWMutex
|
||||||
|
http_PeerID2PubKey map[config.Vertex]string
|
||||||
http_PeerState map[string]*PeerState //the state hash reported by peer
|
http_PeerState map[string]*PeerState //the state hash reported by peer
|
||||||
http_PeerIPs map[string]*HttpPeerLocalIP
|
http_PeerIPs map[string]*HttpPeerLocalIP
|
||||||
http_PeerLastSeen sync.Map // ID -> time.Time
|
|
||||||
http_sconfig *config.SuperConfig
|
http_sconfig *config.SuperConfig
|
||||||
|
|
||||||
http_sconfig_path string
|
http_sconfig_path string
|
||||||
@ -68,6 +68,7 @@ type HttpPeerInfo struct {
|
|||||||
type PeerState struct {
|
type PeerState struct {
|
||||||
NhTableState [32]byte
|
NhTableState [32]byte
|
||||||
PeerInfoState [32]byte
|
PeerInfoState [32]byte
|
||||||
|
LastSeen time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
@ -87,8 +88,8 @@ func get_api_peers(old_State_hash [32]byte) (api_peerinfo config.API_Peers, Stat
|
|||||||
PSKey: peerinfo.PSKey,
|
PSKey: peerinfo.PSKey,
|
||||||
Connurl: make(map[string]int),
|
Connurl: make(map[string]int),
|
||||||
}
|
}
|
||||||
lastSeen, has := http_PeerLastSeen.Load(peerinfo.NodeID)
|
http_maps_lock.RLock()
|
||||||
if has && lastSeen.(time.Time).Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) {
|
if http_PeerState[peerinfo.PubKey].LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now()) {
|
||||||
connV4 := http_device4.GetConnurl(peerinfo.NodeID)
|
connV4 := http_device4.GetConnurl(peerinfo.NodeID)
|
||||||
connV6 := http_device6.GetConnurl(peerinfo.NodeID)
|
connV6 := http_device6.GetConnurl(peerinfo.NodeID)
|
||||||
api_peerinfo[peerinfo.PubKey].Connurl[connV4] = 4
|
api_peerinfo[peerinfo.PubKey].Connurl[connV4] = 4
|
||||||
@ -107,6 +108,7 @@ func get_api_peers(old_State_hash [32]byte) (api_peerinfo config.API_Peers, Stat
|
|||||||
}
|
}
|
||||||
delete(api_peerinfo[peerinfo.PubKey].Connurl, "")
|
delete(api_peerinfo[peerinfo.PubKey].Connurl, "")
|
||||||
}
|
}
|
||||||
|
http_maps_lock.RUnlock()
|
||||||
}
|
}
|
||||||
api_peerinfo_str_byte, _ := json.Marshal(&api_peerinfo)
|
api_peerinfo_str_byte, _ := json.Marshal(&api_peerinfo)
|
||||||
hash_raw := md5.Sum(append(api_peerinfo_str_byte, http_HashSalt...))
|
hash_raw := md5.Sum(append(api_peerinfo_str_byte, http_HashSalt...))
|
||||||
@ -147,6 +149,8 @@ func get_peerinfo(w http.ResponseWriter, r *http.Request) {
|
|||||||
PubKey := PubKeyA[0]
|
PubKey := PubKeyA[0]
|
||||||
State := StateA[0]
|
State := StateA[0]
|
||||||
NodeID := config.Vertex(NID2)
|
NodeID := config.Vertex(NID2)
|
||||||
|
http_maps_lock.RLock()
|
||||||
|
defer http_maps_lock.RUnlock()
|
||||||
if http_PeerID2PubKey[NodeID] != PubKey {
|
if http_PeerID2PubKey[NodeID] != PubKey {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write([]byte("Not found"))
|
w.Write([]byte("Not found"))
|
||||||
@ -221,6 +225,8 @@ func get_nhtable(w http.ResponseWriter, r *http.Request) {
|
|||||||
PubKey := PubKeyA[0]
|
PubKey := PubKeyA[0]
|
||||||
State := StateA[0]
|
State := StateA[0]
|
||||||
NodeID := config.Vertex(NID2)
|
NodeID := config.Vertex(NID2)
|
||||||
|
http_maps_lock.RLock()
|
||||||
|
defer http_maps_lock.RUnlock()
|
||||||
if http_PeerID2PubKey[NodeID] != PubKey {
|
if http_PeerID2PubKey[NodeID] != PubKey {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write([]byte("Not found"))
|
w.Write([]byte("Not found"))
|
||||||
@ -262,16 +268,15 @@ func get_info(w http.ResponseWriter, r *http.Request) {
|
|||||||
Edges: http_graph.GetEdges(),
|
Edges: http_graph.GetEdges(),
|
||||||
Dist: http_graph.GetDtst(),
|
Dist: http_graph.GetDtst(),
|
||||||
}
|
}
|
||||||
|
http_maps_lock.RLock()
|
||||||
for _, peerinfo := range http_sconfig.Peers {
|
for _, peerinfo := range http_sconfig.Peers {
|
||||||
LastSeenStr := ""
|
LastSeenStr := http_PeerState[peerinfo.PubKey].LastSeen.String()
|
||||||
if lastseen, has := http_PeerLastSeen.Load(peerinfo.NodeID); has {
|
|
||||||
LastSeenStr = lastseen.(time.Time).String()
|
|
||||||
}
|
|
||||||
hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{
|
hs.PeerInfo[peerinfo.NodeID] = HttpPeerInfo{
|
||||||
Name: peerinfo.Name,
|
Name: peerinfo.Name,
|
||||||
LastSeen: LastSeenStr,
|
LastSeen: LastSeenStr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
http_maps_lock.RUnlock()
|
||||||
http_StateExpire = time.Now().Add(5 * time.Second)
|
http_StateExpire = time.Now().Add(5 * time.Second)
|
||||||
http_StateString_tmp, _ = json.Marshal(hs)
|
http_StateString_tmp, _ = json.Marshal(hs)
|
||||||
}
|
}
|
||||||
@ -340,7 +345,7 @@ func peeradd(w http.ResponseWriter, r *http.Request) { //Waiting for test
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if http_sconfig.GraphRecalculateSetting.StaticMode == false {
|
if http_sconfig.GraphRecalculateSetting.StaticMode == true {
|
||||||
NhTableStr := r.Form.Get("nexthoptable")
|
NhTableStr := r.Form.Get("nexthoptable")
|
||||||
if NhTableStr == "" {
|
if NhTableStr == "" {
|
||||||
w.WriteHeader(http.StatusExpectationFailed)
|
w.WriteHeader(http.StatusExpectationFailed)
|
||||||
|
@ -287,15 +287,18 @@ func super_peeradd(peerconf config.SuperPeerInfo) error {
|
|||||||
peer6.SetPSK(psk)
|
peer6.SetPSK(psk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
http_maps_lock.Lock()
|
||||||
http_PeerID2PubKey[peerconf.NodeID] = peerconf.PubKey
|
http_PeerID2PubKey[peerconf.NodeID] = peerconf.PubKey
|
||||||
http_PeerState[peerconf.PubKey] = &PeerState{}
|
http_PeerState[peerconf.PubKey] = &PeerState{}
|
||||||
http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{}
|
http_PeerIPs[peerconf.PubKey] = &HttpPeerLocalIP{}
|
||||||
http_PeerLastSeen.Store(peerconf.NodeID, time.Time{})
|
http_maps_lock.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func super_peerdel(toDelete config.Vertex) {
|
func super_peerdel(toDelete config.Vertex) {
|
||||||
|
http_maps_lock.RLock()
|
||||||
PubKey := http_PeerID2PubKey[toDelete]
|
PubKey := http_PeerID2PubKey[toDelete]
|
||||||
|
http_maps_lock.RUnlock()
|
||||||
UpdateErrorMsg := path.UpdateErrorMsg{
|
UpdateErrorMsg := path.UpdateErrorMsg{
|
||||||
Node_id: toDelete,
|
Node_id: toDelete,
|
||||||
Action: path.Shutdown,
|
Action: path.Shutdown,
|
||||||
@ -322,11 +325,11 @@ func super_peerdel(toDelete config.Vertex) {
|
|||||||
http_device4.RemovePeerByID(toDelete)
|
http_device4.RemovePeerByID(toDelete)
|
||||||
http_device6.RemovePeerByID(toDelete)
|
http_device6.RemovePeerByID(toDelete)
|
||||||
http_graph.RemoveVirt(toDelete, true, false)
|
http_graph.RemoveVirt(toDelete, true, false)
|
||||||
http_PeerLastSeen.Delete(toDelete)
|
http_maps_lock.Lock()
|
||||||
|
|
||||||
delete(http_PeerState, PubKey)
|
delete(http_PeerState, PubKey)
|
||||||
delete(http_PeerIPs, PubKey)
|
delete(http_PeerIPs, PubKey)
|
||||||
delete(http_PeerID2PubKey, toDelete)
|
delete(http_PeerID2PubKey, toDelete)
|
||||||
|
http_maps_lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
||||||
@ -335,7 +338,8 @@ func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
|||||||
case reg_msg := <-events.Event_server_register:
|
case reg_msg := <-events.Event_server_register:
|
||||||
var should_push_peer bool
|
var should_push_peer bool
|
||||||
var should_push_nh bool
|
var should_push_nh bool
|
||||||
http_PeerLastSeen.Store(reg_msg.Node_id, time.Now())
|
http_maps_lock.RLock()
|
||||||
|
http_PeerState[http_PeerID2PubKey[reg_msg.Node_id]].LastSeen = time.Now()
|
||||||
if reg_msg.Node_id < config.Special_NodeID {
|
if reg_msg.Node_id < config.Special_NodeID {
|
||||||
PubKey := http_PeerID2PubKey[reg_msg.Node_id]
|
PubKey := http_PeerID2PubKey[reg_msg.Node_id]
|
||||||
if bytes.Equal(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) == false {
|
if bytes.Equal(http_PeerState[PubKey].NhTableState[:], reg_msg.NhStateHash[:]) == false {
|
||||||
@ -352,11 +356,12 @@ func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
|||||||
}
|
}
|
||||||
var peer_state_changed bool
|
var peer_state_changed bool
|
||||||
http_PeerInfo, http_PeerInfo_hash, peer_state_changed = get_api_peers(http_PeerInfo_hash)
|
http_PeerInfo, http_PeerInfo_hash, peer_state_changed = get_api_peers(http_PeerInfo_hash)
|
||||||
|
http_maps_lock.RUnlock()
|
||||||
if should_push_peer || peer_state_changed {
|
if should_push_peer || peer_state_changed {
|
||||||
PushPeerinfo()
|
PushPeerinfo(false)
|
||||||
}
|
}
|
||||||
if should_push_nh {
|
if should_push_nh {
|
||||||
PushNhTable()
|
PushNhTable(false)
|
||||||
}
|
}
|
||||||
case <-events.Event_server_NhTable_changed:
|
case <-events.Event_server_NhTable_changed:
|
||||||
NhTable := graph.GetNHTable()
|
NhTable := graph.GetNHTable()
|
||||||
@ -366,7 +371,7 @@ func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
|||||||
new_hash_str_byte := []byte(new_hash_str)
|
new_hash_str_byte := []byte(new_hash_str)
|
||||||
copy(http_NhTable_Hash[:], new_hash_str_byte)
|
copy(http_NhTable_Hash[:], new_hash_str_byte)
|
||||||
http_NhTableStr = NhTablestr
|
http_NhTableStr = NhTablestr
|
||||||
PushNhTable()
|
PushNhTable(false)
|
||||||
case pong_msg := <-events.Event_server_pong:
|
case pong_msg := <-events.Event_server_pong:
|
||||||
changed := graph.UpdateLentancy(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, true, true)
|
changed := graph.UpdateLentancy(pong_msg.Src_nodeID, pong_msg.Dst_nodeID, pong_msg.Timediff, true, true)
|
||||||
if changed {
|
if changed {
|
||||||
@ -378,21 +383,29 @@ func Event_server_event_hendler(graph *path.IG, events path.SUPER_Events) {
|
|||||||
copy(http_NhTable_Hash[:], new_hash_str_byte)
|
copy(http_NhTable_Hash[:], new_hash_str_byte)
|
||||||
copy(graph.NhTableHash[:], new_hash_str_byte)
|
copy(graph.NhTableHash[:], new_hash_str_byte)
|
||||||
http_NhTableStr = NhTablestr
|
http_NhTableStr = NhTablestr
|
||||||
PushNhTable()
|
PushNhTable(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RoutinePushSettings(interval time.Duration) {
|
func RoutinePushSettings(interval time.Duration) {
|
||||||
|
force := false
|
||||||
|
var lastforce time.Time
|
||||||
for {
|
for {
|
||||||
time.Sleep(interval)
|
if time.Now().After(lastforce.Add(interval)) {
|
||||||
PushNhTable()
|
lastforce = time.Now()
|
||||||
PushPeerinfo()
|
force = true
|
||||||
|
} else {
|
||||||
|
force = false
|
||||||
|
}
|
||||||
|
PushNhTable(force)
|
||||||
|
PushPeerinfo(false)
|
||||||
|
time.Sleep(path.S2TD(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func PushNhTable() {
|
func PushNhTable(force bool) {
|
||||||
body, err := path.GetByte(path.UpdateNhTableMsg{
|
body, err := path.GetByte(path.UpdateNhTableMsg{
|
||||||
State_hash: http_NhTable_Hash,
|
State_hash: http_NhTable_Hash,
|
||||||
})
|
})
|
||||||
@ -407,7 +420,10 @@ func PushNhTable() {
|
|||||||
header.SetSrc(config.SuperNodeMessage)
|
header.SetSrc(config.SuperNodeMessage)
|
||||||
header.SetTTL(0)
|
header.SetTTL(0)
|
||||||
copy(buf[path.EgHeaderLen:], body)
|
copy(buf[path.EgHeaderLen:], body)
|
||||||
for pkstr, _ := range http_PeerState {
|
http_maps_lock.RLock()
|
||||||
|
for pkstr, peerstate := range http_PeerState {
|
||||||
|
isAlive := peerstate.LastSeen.Add(path.S2TD(http_sconfig.GraphRecalculateSetting.NodeReportTimeout)).After(time.Now())
|
||||||
|
if (force && isAlive) || peerstate.NhTableState != http_NhTable_Hash {
|
||||||
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" {
|
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil && peer.GetEndpointDstStr() != "" {
|
||||||
http_device4.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
|
http_device4.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
|
||||||
}
|
}
|
||||||
@ -415,9 +431,11 @@ func PushNhTable() {
|
|||||||
http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
|
http_device6.SendPacket(peer, path.UpdateNhTable, buf, device.MessageTransportOffsetContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
http_maps_lock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func PushPeerinfo() {
|
func PushPeerinfo(force bool) {
|
||||||
body, err := path.GetByte(path.UpdatePeerMsg{
|
body, err := path.GetByte(path.UpdatePeerMsg{
|
||||||
State_hash: http_PeerInfo_hash,
|
State_hash: http_PeerInfo_hash,
|
||||||
})
|
})
|
||||||
@ -432,8 +450,9 @@ func PushPeerinfo() {
|
|||||||
header.SetSrc(config.SuperNodeMessage)
|
header.SetSrc(config.SuperNodeMessage)
|
||||||
header.SetTTL(0)
|
header.SetTTL(0)
|
||||||
copy(buf[path.EgHeaderLen:], body)
|
copy(buf[path.EgHeaderLen:], body)
|
||||||
|
http_maps_lock.RLock()
|
||||||
for pkstr, peerstate := range http_PeerState {
|
for pkstr, peerstate := range http_PeerState {
|
||||||
if peerstate.PeerInfoState != http_PeerInfo_hash {
|
if force || peerstate.PeerInfoState != http_PeerInfo_hash {
|
||||||
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil {
|
if peer := http_device4.LookupPeerByStr(pkstr); peer != nil {
|
||||||
http_device4.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent)
|
http_device4.SendPacket(peer, path.UpdatePeer, buf, device.MessageTransportOffsetContent)
|
||||||
}
|
}
|
||||||
@ -442,6 +461,7 @@ func PushPeerinfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
http_maps_lock.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) {
|
func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) {
|
||||||
|
@ -65,6 +65,18 @@ func (o *OrderedMap) Set(key string, value interface{}) {
|
|||||||
o.values[key] = value
|
o.values[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *OrderedMap) LoadOrStore(key string, value interface{}) (interface{}, bool) {
|
||||||
|
o.rwLock.Lock()
|
||||||
|
defer o.rwLock.Unlock()
|
||||||
|
_, exists := o.values[key]
|
||||||
|
if !exists {
|
||||||
|
o.keys = append(o.keys, key)
|
||||||
|
o.values[key] = value
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
return o.values[key], true
|
||||||
|
}
|
||||||
|
|
||||||
func (o *OrderedMap) Delete(key string) {
|
func (o *OrderedMap) Delete(key string) {
|
||||||
// check key is in use
|
// check key is in use
|
||||||
o.rwLock.Lock()
|
o.rwLock.Lock()
|
||||||
|
88
tap/tap_fd.go
Normal file
88
tap/tap_fd.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package tap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FdTap struct {
|
||||||
|
name string
|
||||||
|
mtu int
|
||||||
|
fileRX *os.File
|
||||||
|
fileTX *os.File
|
||||||
|
events chan Event
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates and returns a new TUN interface for the application.
|
||||||
|
func CreateFdTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (tapdev Device, err error) {
|
||||||
|
// Setup TUN Config
|
||||||
|
fdRXstr, has := os.LookupEnv("EG_FD_RX")
|
||||||
|
if !has {
|
||||||
|
return nil, errors.New("Need Environment Variable EG_FD_RX")
|
||||||
|
}
|
||||||
|
fdRX, err := strconv.Atoi(fdRXstr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fdTxstr, has := os.LookupEnv("EG_FD_TX")
|
||||||
|
if !has {
|
||||||
|
return nil, errors.New("Need Environment Variable EG_FD_TX")
|
||||||
|
}
|
||||||
|
fdTX, err := strconv.Atoi(fdTxstr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileRX := os.NewFile(uintptr(fdRX), "pipeRX")
|
||||||
|
fileTX := os.NewFile(uintptr(fdTX), "pipeTX")
|
||||||
|
|
||||||
|
tapdev = &FdTap{
|
||||||
|
name: iconfig.Name,
|
||||||
|
fileRX: fileRX,
|
||||||
|
fileTX: fileTX,
|
||||||
|
events: make(chan Event, 1<<5),
|
||||||
|
}
|
||||||
|
tapdev.Events() <- EventUp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMTU sets the Maximum Tansmission Unit Size for a
|
||||||
|
// Packet on the interface.
|
||||||
|
|
||||||
|
func (tap *FdTap) Read(buf []byte, offset int) (int, error) {
|
||||||
|
size, err := tap.fileRX.Read(buf[offset:])
|
||||||
|
return size, err
|
||||||
|
} // read a packet from the device (without any additional headers)
|
||||||
|
func (tap *FdTap) Write(buf []byte, offset int) (size int, err error) {
|
||||||
|
packet := buf[offset:]
|
||||||
|
size, err = tap.fileRX.Write(packet)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
//err = syscall.Fsync(int(tap.fileTX.Fd()))
|
||||||
|
//err = tap.fileTX.Sync()
|
||||||
|
return
|
||||||
|
} // writes a packet to the device (without any additional headers)
|
||||||
|
func (tap *FdTap) Flush() error {
|
||||||
|
return nil
|
||||||
|
} // flush all previous writes to the device
|
||||||
|
func (tap *FdTap) MTU() (int, error) {
|
||||||
|
return tap.mtu, nil
|
||||||
|
} // returns the MTU of the device
|
||||||
|
func (tap *FdTap) Name() (string, error) {
|
||||||
|
return tap.name, nil
|
||||||
|
} // fetches and returns the current name
|
||||||
|
func (tap *FdTap) Events() chan Event {
|
||||||
|
return tap.events
|
||||||
|
} // returns a constant channel of events related to the device
|
||||||
|
func (tap *FdTap) Close() error {
|
||||||
|
tap.events <- EventDown
|
||||||
|
tap.fileRX.Close()
|
||||||
|
tap.fileTX.Close()
|
||||||
|
close(tap.events)
|
||||||
|
return nil
|
||||||
|
} // stops the device and closes the event channel
|
154
tap/tap_sock.go
Normal file
154
tap/tap_sock.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package tap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/KusakabeSi/EtherGuardVPN/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SockServerTap struct {
|
||||||
|
name string
|
||||||
|
mtu int
|
||||||
|
protocol string
|
||||||
|
server *net.Listener
|
||||||
|
connRx *net.Conn
|
||||||
|
connTx *net.Conn
|
||||||
|
static bool
|
||||||
|
|
||||||
|
closed bool
|
||||||
|
events chan Event
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates and returns a new TUN interface for the application.
|
||||||
|
func CreateSockTAP(iconfig config.InterfaceConf, protocol string, NodeID config.Vertex) (tapdev Device, err error) {
|
||||||
|
// Setup TUN Config
|
||||||
|
|
||||||
|
tap := &SockServerTap{
|
||||||
|
name: iconfig.Name,
|
||||||
|
mtu: 1500,
|
||||||
|
protocol: protocol,
|
||||||
|
server: nil,
|
||||||
|
connRx: nil,
|
||||||
|
connTx: nil,
|
||||||
|
static: false,
|
||||||
|
closed: false,
|
||||||
|
events: make(chan Event, 1<<5),
|
||||||
|
}
|
||||||
|
|
||||||
|
if iconfig.RecvAddr == "" && iconfig.SendAddr == "" {
|
||||||
|
return nil, errors.New("At least one of RecvAddr or SendAddr required.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if iconfig.RecvAddr != "" {
|
||||||
|
server, err := net.Listen(protocol, iconfig.RecvAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tap.server = &server
|
||||||
|
go tap.RoutineAcceptConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
if iconfig.SendAddr != "" {
|
||||||
|
client, err := net.Dial(protocol, iconfig.SendAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tap.connTx = &client
|
||||||
|
tap.static = true
|
||||||
|
if tap.server == nil {
|
||||||
|
tap.connRx = &client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tapdev = tap
|
||||||
|
tapdev.Events() <- EventUp
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tap *SockServerTap) RoutineAcceptConnection() {
|
||||||
|
if tap.server == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
fd, err := (*tap.server).Accept()
|
||||||
|
if tap.closed == true {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
println("accept error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if tap.connRx != nil {
|
||||||
|
(*tap.connRx).Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
tap.connRx = &fd
|
||||||
|
if tap.static == false {
|
||||||
|
tap.connTx = &fd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMTU sets the Maximum Tansmission Unit Size for a
|
||||||
|
// Packet on the interface.
|
||||||
|
|
||||||
|
func (tap *SockServerTap) Read(buf []byte, offset int) (size int, err error) {
|
||||||
|
if tap.closed {
|
||||||
|
return 0, errors.New("Tap closed")
|
||||||
|
}
|
||||||
|
if tap.connRx == nil {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
size, err = (*tap.connRx).Read(buf[offset:])
|
||||||
|
if err != nil && tap.server != nil {
|
||||||
|
tap.connRx = nil
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} // read a packet from the device (without any additional headers)
|
||||||
|
func (tap *SockServerTap) Write(buf []byte, offset int) (size int, err error) {
|
||||||
|
if tap.closed {
|
||||||
|
return 0, errors.New("Tap closed")
|
||||||
|
}
|
||||||
|
if tap.connTx == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
size, err = (*tap.connTx).Write(buf[offset:])
|
||||||
|
if serr, ok := err.(*net.OpError); ok && tap.server != nil {
|
||||||
|
if serr.Err.Error() == "use of closed network connection" || serr.Err.Error() == "EOF" {
|
||||||
|
tap.connTx = nil
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} // writes a packet to the device (without any additional headers)
|
||||||
|
func (tap *SockServerTap) Flush() error {
|
||||||
|
return nil
|
||||||
|
} // flush all previous writes to the device
|
||||||
|
func (tap *SockServerTap) MTU() (int, error) {
|
||||||
|
return tap.mtu, nil
|
||||||
|
} // returns the MTU of the device
|
||||||
|
func (tap *SockServerTap) Name() (string, error) {
|
||||||
|
return tap.name, nil
|
||||||
|
} // fetches and returns the current name
|
||||||
|
func (tap *SockServerTap) Events() chan Event {
|
||||||
|
return tap.events
|
||||||
|
} // returns a constant channel of events related to the device
|
||||||
|
func (tap *SockServerTap) Close() error {
|
||||||
|
tap.events <- EventDown
|
||||||
|
tap.closed = true
|
||||||
|
if tap.connRx != nil {
|
||||||
|
(*tap.connRx).Close()
|
||||||
|
}
|
||||||
|
if tap.connTx != nil {
|
||||||
|
(*tap.connTx).Close()
|
||||||
|
}
|
||||||
|
if tap.server != nil {
|
||||||
|
(*tap.server).Close()
|
||||||
|
}
|
||||||
|
close(tap.events)
|
||||||
|
return nil
|
||||||
|
} // stops the device and closes the event channel
|
@ -1,6 +1,7 @@
|
|||||||
package tap
|
package tap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
@ -12,33 +13,55 @@ type UdpSockTap struct {
|
|||||||
mtu int
|
mtu int
|
||||||
recv *net.UDPConn
|
recv *net.UDPConn
|
||||||
send *net.UDPAddr
|
send *net.UDPAddr
|
||||||
|
static bool
|
||||||
L2mode L2MODE
|
L2mode L2MODE
|
||||||
macaddr MacAddress
|
|
||||||
events chan Event
|
events chan Event
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates and returns a new TUN interface for the application.
|
// New creates and returns a new TUN interface for the application.
|
||||||
func CreateUDPSockTAP(iconfig config.InterfaceConf,NodeID config.Vertex, listenAddr *net.UDPAddr, sendAddr *net.UDPAddr) (tapdev Device, err error) {
|
func CreateUDPSockTAP(iconfig config.InterfaceConf, NodeID config.Vertex) (tapdev Device, err error) {
|
||||||
// Setup TUN Config
|
// Setup TUN Config
|
||||||
|
|
||||||
listener, err := net.ListenUDP("udp", listenAddr)
|
tap := &UdpSockTap{
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
}
|
|
||||||
macaddr, err := GetMacAddr(iconfig.MacAddrPrefix,uint32(NodeID))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
tapdev = &UdpSockTap{
|
|
||||||
name: iconfig.Name,
|
name: iconfig.Name,
|
||||||
mtu: 1500,
|
mtu: 1500,
|
||||||
recv: listener,
|
recv: nil,
|
||||||
send: sendAddr,
|
send: nil,
|
||||||
macaddr: macaddr,
|
static: false,
|
||||||
L2mode: GetL2Mode(iconfig.L2HeaderMode),
|
L2mode: GetL2Mode(iconfig.L2HeaderMode),
|
||||||
events: make(chan Event, 1<<5),
|
events: make(chan Event, 1<<5),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if iconfig.RecvAddr == "" && iconfig.SendAddr == "" {
|
||||||
|
return nil, errors.New("At least one of RecvAddr or SendAddr required.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if iconfig.RecvAddr == "" {
|
||||||
|
iconfig.RecvAddr = ":0"
|
||||||
|
}
|
||||||
|
listenAddr, err := net.ResolveUDPAddr("udp", iconfig.RecvAddr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
listener, err := net.ListenUDP("udp", listenAddr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tap.recv = listener
|
||||||
|
|
||||||
|
if iconfig.SendAddr != "" {
|
||||||
|
sendAddr, err := net.ResolveUDPAddr("udp", iconfig.SendAddr)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tap.send = sendAddr
|
||||||
|
tap.static = true
|
||||||
|
}
|
||||||
|
|
||||||
|
tapdev = tap
|
||||||
tapdev.Events() <- EventUp
|
tapdev.Events() <- EventUp
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -47,46 +70,15 @@ func CreateUDPSockTAP(iconfig config.InterfaceConf,NodeID config.Vertex, listenA
|
|||||||
// Packet on the interface.
|
// Packet on the interface.
|
||||||
|
|
||||||
func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) {
|
func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) {
|
||||||
switch tap.L2mode {
|
size, source, err := tap.recv.ReadFromUDP(buf[offset:])
|
||||||
case KeyboardDebug:
|
if tap.static == false {
|
||||||
size, _, err := tap.recv.ReadFromUDP(buf[offset+10:])
|
tap.send = source
|
||||||
packet := buf[offset:]
|
|
||||||
src := Charform2mac(packet[11])
|
|
||||||
dst := Charform2mac(packet[10])
|
|
||||||
copy(packet[0:6], dst[:])
|
|
||||||
copy(packet[6:12], src[:])
|
|
||||||
return size + 10, err
|
|
||||||
case BoardcastAndNodeID:
|
|
||||||
size, _, err := tap.recv.ReadFromUDP(buf[offset+12:])
|
|
||||||
packet := buf[offset:]
|
|
||||||
src := tap.macaddr
|
|
||||||
dst := Charform2mac('b')
|
|
||||||
copy(packet[0:6], dst[:])
|
|
||||||
copy(packet[6:12], src[:])
|
|
||||||
return size + 12, err
|
|
||||||
default:
|
|
||||||
size, _, err := tap.recv.ReadFromUDP(buf[offset:])
|
|
||||||
return size, err
|
|
||||||
}
|
}
|
||||||
|
return size, err
|
||||||
} // read a packet from the device (without any additional headers)
|
} // read a packet from the device (without any additional headers)
|
||||||
func (tap *UdpSockTap) Write(buf []byte, offset int) (size int, err error) {
|
func (tap *UdpSockTap) Write(buf []byte, offset int) (size int, err error) {
|
||||||
packet := buf[offset:]
|
size, err = tap.recv.WriteToUDP(buf[offset:], tap.send)
|
||||||
switch tap.L2mode {
|
|
||||||
case KeyboardDebug:
|
|
||||||
src := Mac2charForm(packet[6:12])
|
|
||||||
dst := Mac2charForm(packet[0:6])
|
|
||||||
packet[10] = dst
|
|
||||||
packet[11] = src
|
|
||||||
size, err = tap.recv.WriteToUDP(packet[10:], tap.send)
|
|
||||||
return
|
return
|
||||||
case BoardcastAndNodeID:
|
|
||||||
size, err = tap.recv.WriteToUDP(packet[12:], tap.send)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
size, err = tap.recv.WriteToUDP(packet, tap.send)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} // writes a packet to the device (without any additional headers)
|
} // writes a packet to the device (without any additional headers)
|
||||||
func (tap *UdpSockTap) Flush() error {
|
func (tap *UdpSockTap) Flush() error {
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
Reference in New Issue
Block a user