mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 08:20:28 +00:00
Version 0.2.1 (#130)
* switch address range from fd00::/8 to the deprecated 0200::/7 range * Fix launchd script path and amend debian control file * fix address/prefix code, platform specific parts still need testing * macos * cleanup old ugly session MTU code that only mattered with lossy UDP fragments * Fix debian control file * Let's try this again * tcp/socks cleanup * comment * avoid the proxy.SOCK5 connection attempt unless we're actually going to use the dialer * Update generate.sh * prevent parent nodes from forcing coord oscillation, have dht.handleRes clean up the old request info immediately * address range changes * Update README.md Consistently remove leading zeros from addresses in the readme. * Update yggdrasil.go * Collect yggdrasilctl during CI build * Fix CircleCI after fat-fingered copypasta * Fix for Windows * clean up main yggdrasil.go imports and run gofmt
This commit is contained in:
parent
8c29f4b6dc
commit
0ec5f1c02c
@ -21,42 +21,42 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Build for Linux (including Debian packages)
|
name: Build for Linux (including Debian packages)
|
||||||
command: |
|
command: |
|
||||||
PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64;
|
PKGARCH=amd64 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-amd64;
|
||||||
PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386;
|
PKGARCH=i386 sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-i386;
|
||||||
PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel;
|
PKGARCH=mipsel sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mipsel && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-mipsel;
|
||||||
PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips;
|
PKGARCH=mips sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-mips && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-mips;
|
||||||
PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armhf;
|
PKGARCH=armhf sh contrib/deb/generate.sh && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-linux-armh && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-linux-armhf;
|
||||||
mv *.deb /tmp/upload/
|
mv *.deb /tmp/upload/
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build for macOS
|
name: Build for macOS
|
||||||
command: |
|
command: |
|
||||||
GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64;
|
GOOS=darwin GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-amd64;
|
||||||
GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386;
|
GOOS=darwin GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-darwin-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-darwin-i386;
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build for OpenBSD
|
name: Build for OpenBSD
|
||||||
command: |
|
command: |
|
||||||
GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64;
|
GOOS=openbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-openbsd-amd64;
|
||||||
GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386;
|
GOOS=openbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-openbsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-openbsd-i386;
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build for FreeBSD
|
name: Build for FreeBSD
|
||||||
command: |
|
command: |
|
||||||
GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64;
|
GOOS=freebsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-freebsd-amd64;
|
||||||
GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386;
|
GOOS=freebsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-freebsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-freebsd-i386;
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build for NetBSD
|
name: Build for NetBSD
|
||||||
command: |
|
command: |
|
||||||
GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64;
|
GOOS=netbsd GOARCH=amd64 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-amd64 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-netbsd-amd64;
|
||||||
GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386;
|
GOOS=netbsd GOARCH=386 ./build && mv yggdrasil /tmp/upload/$CINAME-$CIVERSION-netbsd-i386 && mv yggdrasilctl /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-netbsd-i386;
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build for Windows
|
name: Build for Windows
|
||||||
command: |
|
command: |
|
||||||
GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe;
|
GOOS=windows GOARCH=amd64 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-amd64.exe && mv yggdrasilctl.exe /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-amd64.exe;
|
||||||
GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe;
|
GOOS=windows GOARCH=386 ./build && mv yggdrasil.exe /tmp/upload/$CINAME-$CIVERSION-windows-i386.exe && mv yggdrasilctl.exe /tmp/upload/$CINAME-$CIVERSION-yggdrasilctl-windows-i386.exe;
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: Build for EdgeRouter
|
name: Build for EdgeRouter
|
||||||
|
14
README.md
14
README.md
@ -85,7 +85,7 @@ journalctl -u yggdrasil
|
|||||||
|
|
||||||
- Tested and working on Windows 7 and Windows 10, and should work on any recent versions of Windows, but it depends on the [OpenVPN TAP driver](https://openvpn.net/index.php/open-source/downloads.html) being installed first.
|
- Tested and working on Windows 7 and Windows 10, and should work on any recent versions of Windows, but it depends on the [OpenVPN TAP driver](https://openvpn.net/index.php/open-source/downloads.html) being installed first.
|
||||||
- Has been proven to work with both the [NDIS 5](https://swupdate.openvpn.org/community/releases/tap-windows-9.9.2_3.exe) (`tap-windows-9.9.2_3`) driver and the [NDIS 6](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe) (`tap-windows-9.21.2`) driver, however there are substantial performance issues with the NDIS 6 driver therefore it is recommended to use the NDIS 5 driver instead.
|
- Has been proven to work with both the [NDIS 5](https://swupdate.openvpn.org/community/releases/tap-windows-9.9.2_3.exe) (`tap-windows-9.9.2_3`) driver and the [NDIS 6](https://swupdate.openvpn.org/community/releases/tap-windows-9.21.2.exe) (`tap-windows-9.21.2`) driver, however there are substantial performance issues with the NDIS 6 driver therefore it is recommended to use the NDIS 5 driver instead.
|
||||||
- Be aware that connectivity issues can occur on Windows if multiple IPv6 addresses from the `fd00::/8` prefix are assigned to the TAP interface. If this happens, then you may need to manually remove the old/unused addresses from the interface (though the code has a workaround in place to do this automatically in some cases).
|
- Be aware that connectivity issues can occur on Windows if multiple IPv6 addresses from the `200::/7` prefix are assigned to the TAP interface. If this happens, then you may need to manually remove the old/unused addresses from the interface (though the code has a workaround in place to do this automatically in some cases).
|
||||||
- TUN mode is not supported on Windows.
|
- TUN mode is not supported on Windows.
|
||||||
- Yggdrasil can be installed as a Windows service so that it runs automatically in the background. From an Administrator Command Prompt:
|
- Yggdrasil can be installed as a Windows service so that it runs automatically in the background. From an Administrator Command Prompt:
|
||||||
```
|
```
|
||||||
@ -105,26 +105,26 @@ sc create yggdrasil binpath= "\"C:\path\to\yggdrasil.exe\" -autoconf"
|
|||||||
|
|
||||||
## Optional: advertise a prefix locally
|
## Optional: advertise a prefix locally
|
||||||
|
|
||||||
Suppose a node has generated the address: `fd00:1111:2222:3333:4444:5555:6666:7777`
|
Suppose a node has generated the address: `200:1111:2222:3333:4444:5555:6666:7777`
|
||||||
|
|
||||||
Then the node may also use addresses from the prefix: `fd80:1111:2222:3333::/64` (note the `fd00` changed to `fd80`, a separate `/9` is used for prefixes, but the rest of the first 64 bits are the same).
|
Then the node may also use addresses from the prefix: `300:1111:2222:3333::/64` (note the `200` changed to `300`, a separate `/8` is used for prefixes, but the rest of the first 64 bits are the same).
|
||||||
|
|
||||||
To advertise this prefix and a route to `fd00::/8`, the following seems to work on the developers' networks:
|
To advertise this prefix and a route to `200::/7`, the following seems to work on the developers' networks:
|
||||||
|
|
||||||
1. Enable IPv6 forwarding (e.g. `sysctl -w net.ipv6.conf.all.forwarding=1` or add it to sysctl.conf).
|
1. Enable IPv6 forwarding (e.g. `sysctl -w net.ipv6.conf.all.forwarding=1` or add it to sysctl.conf).
|
||||||
|
|
||||||
2. `ip addr add fd80:1111:2222:3333::1/64 dev eth0` or similar, to assign an address for the router to use in that prefix, where the LAN is reachable through `eth0`.
|
2. `ip addr add 300:1111:2222:3333::1/64 dev eth0` or similar, to assign an address for the router to use in that prefix, where the LAN is reachable through `eth0`.
|
||||||
|
|
||||||
3. Install/run `radvd` with something like the following in `/etc/radvd.conf`:
|
3. Install/run `radvd` with something like the following in `/etc/radvd.conf`:
|
||||||
```
|
```
|
||||||
interface eth0
|
interface eth0
|
||||||
{
|
{
|
||||||
AdvSendAdvert on;
|
AdvSendAdvert on;
|
||||||
prefix fd80:1111:2222:3333::/64 {
|
prefix 300:1111:2222:3333::/64 {
|
||||||
AdvOnLink on;
|
AdvOnLink on;
|
||||||
AdvAutonomous on;
|
AdvAutonomous on;
|
||||||
};
|
};
|
||||||
route fd00::/8 {};
|
route 200::/7 {};
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ PKGNAME=$(sh contrib/semver/name.sh)
|
|||||||
PKGVERSION=$(sh contrib/semver/version.sh | cut -c 2-)
|
PKGVERSION=$(sh contrib/semver/version.sh | cut -c 2-)
|
||||||
PKGARCH=${PKGARCH-amd64}
|
PKGARCH=${PKGARCH-amd64}
|
||||||
PKGFILE=$PKGNAME-$PKGVERSION-$PKGARCH.deb
|
PKGFILE=$PKGNAME-$PKGVERSION-$PKGARCH.deb
|
||||||
|
PKGREPLACES=yggdrasil
|
||||||
|
|
||||||
|
if [ $PKGBRANCH = "master" ]; then
|
||||||
|
PKGREPLACES=yggdrasil-develop
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build
|
if [ $PKGARCH = "amd64" ]; then GOARCH=amd64 GOOS=linux ./build
|
||||||
elif [ $PKGARCH = "i386" ]; then GOARCH=386 GOOS=linux ./build
|
elif [ $PKGARCH = "i386" ]; then GOARCH=386 GOOS=linux ./build
|
||||||
@ -34,7 +39,7 @@ mkdir -p /tmp/$PKGNAME/usr/bin/
|
|||||||
mkdir -p /tmp/$PKGNAME/etc/systemd/system/
|
mkdir -p /tmp/$PKGNAME/etc/systemd/system/
|
||||||
|
|
||||||
cat > /tmp/$PKGNAME/debian/changelog << EOF
|
cat > /tmp/$PKGNAME/debian/changelog << EOF
|
||||||
Please see https://github.com/Arceliar/yggdrasil-go/
|
Please see https://github.com/yggdrasil-network/yggdrasil-go/
|
||||||
EOF
|
EOF
|
||||||
echo 9 > /tmp/$PKGNAME/debian/compat
|
echo 9 > /tmp/$PKGNAME/debian/compat
|
||||||
cat > /tmp/$PKGNAME/debian/control << EOF
|
cat > /tmp/$PKGNAME/debian/control << EOF
|
||||||
@ -43,15 +48,17 @@ Version: $PKGVERSION
|
|||||||
Section: contrib/net
|
Section: contrib/net
|
||||||
Priority: extra
|
Priority: extra
|
||||||
Architecture: $PKGARCH
|
Architecture: $PKGARCH
|
||||||
|
Replaces: $PKGREPLACES
|
||||||
|
Conflicts: $PKGREPLACES
|
||||||
Maintainer: Neil Alexander <neilalexander@users.noreply.github.com>
|
Maintainer: Neil Alexander <neilalexander@users.noreply.github.com>
|
||||||
Description: Debian yggdrasil package
|
Description: Debian yggdrasil package
|
||||||
Binary yggdrasil package for Debian and Ubuntu
|
Binary yggdrasil package for Debian and Ubuntu
|
||||||
EOF
|
EOF
|
||||||
cat > /tmp/$PKGNAME/debian/copyright << EOF
|
cat > /tmp/$PKGNAME/debian/copyright << EOF
|
||||||
Please see https://github.com/Arceliar/yggdrasil-go/
|
Please see https://github.com/yggdrasil-network/yggdrasil-go/
|
||||||
EOF
|
EOF
|
||||||
cat > /tmp/$PKGNAME/debian/docs << EOF
|
cat > /tmp/$PKGNAME/debian/docs << EOF
|
||||||
Please see https://github.com/Arceliar/yggdrasil-go/
|
Please see https://github.com/yggdrasil-network/yggdrasil-go/
|
||||||
EOF
|
EOF
|
||||||
cat > /tmp/$PKGNAME/debian/install << EOF
|
cat > /tmp/$PKGNAME/debian/install << EOF
|
||||||
usr/bin/yggdrasil usr/bin
|
usr/bin/yggdrasil usr/bin
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<array>
|
<array>
|
||||||
<string>sh</string>
|
<string>sh</string>
|
||||||
<string>-c</string>
|
<string>-c</string>
|
||||||
<string>/usr/bin/yggdrasil -useconf < /etc/yggdrasil.conf</string>
|
<string>/usr/local/bin/yggdrasil -useconf < /etc/yggdrasil.conf</string>
|
||||||
</array>
|
</array>
|
||||||
<key>KeepAlive</key>
|
<key>KeepAlive</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
@ -7,9 +7,10 @@ type address [16]byte
|
|||||||
type subnet [8]byte
|
type subnet [8]byte
|
||||||
|
|
||||||
// address_prefix is the prefix used for all addresses and subnets in the network.
|
// address_prefix is the prefix used for all addresses and subnets in the network.
|
||||||
// The current implementation requires this to be a multiple of 8 bits.
|
// The current implementation requires this to be a muliple of 8 bits + 7 bits.
|
||||||
|
// The 8th bit of the last byte is used to signal nodes (0) or /64 prefixes (1).
|
||||||
// Nodes that configure this differently will be unable to communicate with eachother, though routing and the DHT machinery *should* still work.
|
// Nodes that configure this differently will be unable to communicate with eachother, though routing and the DHT machinery *should* still work.
|
||||||
var address_prefix = [...]byte{0xfd}
|
var address_prefix = [...]byte{0x02}
|
||||||
|
|
||||||
// isValid returns true if an address falls within the range used by nodes in the network.
|
// isValid returns true if an address falls within the range used by nodes in the network.
|
||||||
func (a *address) isValid() bool {
|
func (a *address) isValid() bool {
|
||||||
@ -18,24 +19,24 @@ func (a *address) isValid() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (*a)[len(address_prefix)]&0x80 == 0
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// isValid returns true if a prefix falls within the range usable by the network.
|
// isValid returns true if a prefix falls within the range usable by the network.
|
||||||
func (s *subnet) isValid() bool {
|
func (s *subnet) isValid() bool {
|
||||||
for idx := range address_prefix {
|
l := len(address_prefix)
|
||||||
|
for idx := range address_prefix[:l-1] {
|
||||||
if (*s)[idx] != address_prefix[idx] {
|
if (*s)[idx] != address_prefix[idx] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (*s)[len(address_prefix)]&0x80 != 0
|
return (*s)[l-1] == address_prefix[l-1]|0x01
|
||||||
}
|
}
|
||||||
|
|
||||||
// address_addrForNodeID takes a *NodeID as an argument and returns an *address.
|
// address_addrForNodeID takes a *NodeID as an argument and returns an *address.
|
||||||
// This address begins with the address prefix.
|
// This subnet begins with the address prefix, with the last bit set to 0 to indicate an address.
|
||||||
// The next bit is 0 for an address, and 1 for a subnet.
|
// The following 8 bits are set to the number of leading 1 bits in the NodeID.
|
||||||
// The following 7 bits are set to the number of leading 1 bits in the NodeID.
|
// The NodeID, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the address.
|
||||||
// The NodeID, excluding the leading 1 bits and the first leading 1 bit, is truncated to the appropriate length and makes up the remainder of the address.
|
|
||||||
func address_addrForNodeID(nid *NodeID) *address {
|
func address_addrForNodeID(nid *NodeID) *address {
|
||||||
// 128 bit address
|
// 128 bit address
|
||||||
// Begins with prefix
|
// Begins with prefix
|
||||||
@ -67,16 +68,15 @@ func address_addrForNodeID(nid *NodeID) *address {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
copy(addr[:], address_prefix[:])
|
copy(addr[:], address_prefix[:])
|
||||||
addr[len(address_prefix)] = ones & 0x7f
|
addr[len(address_prefix)] = ones
|
||||||
copy(addr[len(address_prefix)+1:], temp)
|
copy(addr[len(address_prefix)+1:], temp)
|
||||||
return &addr
|
return &addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// address_subnetForNodeID takes a *NodeID as an argument and returns a *subnet.
|
// address_subnetForNodeID takes a *NodeID as an argument and returns a *subnet.
|
||||||
// This subnet begins with the address prefix.
|
// This subnet begins with the address prefix, with the last bit set to 1 to indicate a prefix.
|
||||||
// The next bit is 0 for an address, and 1 for a subnet.
|
// The following 8 bits are set to the number of leading 1 bits in the NodeID.
|
||||||
// The following 7 bits are set to the number of leading 1 bits in the NodeID.
|
// The NodeID, excluding the leading 1 bits and the first leading 0 bit, is truncated to the appropriate length and makes up the remainder of the subnet.
|
||||||
// The NodeID, excluding the leading 1 bits and the first leading 1 bit, is truncated to the appropriate length and makes up the remainder of the subnet.
|
|
||||||
func address_subnetForNodeID(nid *NodeID) *subnet {
|
func address_subnetForNodeID(nid *NodeID) *subnet {
|
||||||
// Exactly as the address version, with two exceptions:
|
// Exactly as the address version, with two exceptions:
|
||||||
// 1) The first bit after the fixed prefix is a 1 instead of a 0
|
// 1) The first bit after the fixed prefix is a 1 instead of a 0
|
||||||
@ -84,7 +84,7 @@ func address_subnetForNodeID(nid *NodeID) *subnet {
|
|||||||
addr := *address_addrForNodeID(nid)
|
addr := *address_addrForNodeID(nid)
|
||||||
var snet subnet
|
var snet subnet
|
||||||
copy(snet[:], addr[:])
|
copy(snet[:], addr[:])
|
||||||
snet[len(address_prefix)] |= 0x80
|
snet[len(address_prefix)-1] |= 0x01
|
||||||
return &snet
|
return &snet
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ func (a *address) getNodeIDandMask() (*NodeID, *NodeID) {
|
|||||||
// This means truncated leading 1s, first leading 0, and visible part of addr
|
// This means truncated leading 1s, first leading 0, and visible part of addr
|
||||||
var nid NodeID
|
var nid NodeID
|
||||||
var mask NodeID
|
var mask NodeID
|
||||||
ones := int(a[len(address_prefix)] & 0x7f)
|
ones := int(a[len(address_prefix)])
|
||||||
for idx := 0; idx < ones; idx++ {
|
for idx := 0; idx < ones; idx++ {
|
||||||
nid[idx/8] |= 0x80 >> byte(idx%8)
|
nid[idx/8] |= 0x80 >> byte(idx%8)
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ func (s *subnet) getNodeIDandMask() (*NodeID, *NodeID) {
|
|||||||
// As with the address version, but visible parts of the subnet prefix instead
|
// As with the address version, but visible parts of the subnet prefix instead
|
||||||
var nid NodeID
|
var nid NodeID
|
||||||
var mask NodeID
|
var mask NodeID
|
||||||
ones := int(s[len(address_prefix)] & 0x7f)
|
ones := int(s[len(address_prefix)])
|
||||||
for idx := 0; idx < ones; idx++ {
|
for idx := 0; idx < ones; idx++ {
|
||||||
nid[idx/8] |= 0x80 >> byte(idx%8)
|
nid[idx/8] |= 0x80 >> byte(idx%8)
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ func (a *admin) startTunWithMTU(ifname string, iftapmode bool, ifmtu int) error
|
|||||||
_ = a.core.tun.close()
|
_ = a.core.tun.close()
|
||||||
// Then reconfigure and start it
|
// Then reconfigure and start it
|
||||||
addr := a.core.router.addr
|
addr := a.core.router.addr
|
||||||
straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix))
|
straddr := fmt.Sprintf("%s/%v", net.IP(addr[:]).String(), 8*len(address_prefix)-1)
|
||||||
if ifname != "none" {
|
if ifname != "none" {
|
||||||
err := a.core.tun.setup(ifname, iftapmode, straddr, ifmtu)
|
err := a.core.tun.setup(ifname, iftapmode, straddr, ifmtu)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -117,7 +117,7 @@ func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ip := net.IP(c.router.addr[:]).String()
|
ip := net.IP(c.router.addr[:]).String()
|
||||||
if err := c.tun.start(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/8", ip), nc.IfMTU); err != nil {
|
if err := c.tun.start(nc.IfName, nc.IfTAPMode, fmt.Sprintf("%s/%d", ip, 8*len(address_prefix)-1), nc.IfMTU); err != nil {
|
||||||
c.log.Println("Failed to start TUN/TAP")
|
c.log.Println("Failed to start TUN/TAP")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ package yggdrasil
|
|||||||
|
|
||||||
import _ "golang.org/x/net/ipv6" // TODO put this somewhere better
|
import _ "golang.org/x/net/ipv6" // TODO put this somewhere better
|
||||||
|
|
||||||
import "golang.org/x/net/proxy"
|
//import "golang.org/x/net/proxy"
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "net"
|
import "net"
|
||||||
@ -353,6 +353,7 @@ func (c *Core) DEBUG_addPeer(addr string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) {
|
func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) {
|
||||||
go func() {
|
go func() {
|
||||||
dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct)
|
dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct)
|
||||||
@ -370,6 +371,7 @@ func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
//*
|
//*
|
||||||
func (c *Core) DEBUG_setupAndStartGlobalTCPInterface(addrport string) {
|
func (c *Core) DEBUG_setupAndStartGlobalTCPInterface(addrport string) {
|
||||||
@ -384,7 +386,7 @@ func (c *Core) DEBUG_getGlobalTCPAddr() *net.TCPAddr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) DEBUG_addTCPConn(saddr string) {
|
func (c *Core) DEBUG_addTCPConn(saddr string) {
|
||||||
c.tcp.call(saddr)
|
c.tcp.call(saddr, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//*/
|
//*/
|
||||||
|
@ -126,8 +126,10 @@ func (t *dht) handleReq(req *dhtReq) {
|
|||||||
key: req.Key,
|
key: req.Key,
|
||||||
coords: req.Coords,
|
coords: req.Coords,
|
||||||
}
|
}
|
||||||
t.insertIfNew(&info, false) // This seems DoSable (we just trust their coords...)
|
// For bootstrapping to work, we need to add these nodes to the table
|
||||||
//if req.dest != t.nodeID { t.ping(&info, info.getNodeID()) } // Or spam...
|
// Using insertIfNew, they can lie about coords, but searches will route around them
|
||||||
|
// Using the mill would mean trying to block off the mill becomes an attack vector
|
||||||
|
t.insertIfNew(&info, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads a lookup response, checks that we had sent a matching request, and processes the response info.
|
// Reads a lookup response, checks that we had sent a matching request, and processes the response info.
|
||||||
@ -142,6 +144,7 @@ func (t *dht) handleRes(res *dhtRes) {
|
|||||||
if !isIn {
|
if !isIn {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
delete(reqs, res.Dest)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
rinfo := dhtInfo{
|
rinfo := dhtInfo{
|
||||||
key: res.Key,
|
key: res.Key,
|
||||||
|
@ -252,7 +252,7 @@ func (i *icmpv6) handle_ndp(in []byte) ([]byte, error) {
|
|||||||
case source.isValid():
|
case source.isValid():
|
||||||
case snet.isValid():
|
case snet.isValid():
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Not an NDP for fd00::/8")
|
return nil, errors.New("Not an NDP for 0200::/7")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create our NDP message body response
|
// Create our NDP message body response
|
||||||
|
@ -437,41 +437,14 @@ func (sinfo *sessionInfo) doSend(bs []byte) {
|
|||||||
// TODO? remove the MTU updating part? That should never happen with TCP peers, and the old UDP code that caused it was removed (and if replaced, should be replaced with something that can reliably send messages with an arbitrary size).
|
// TODO? remove the MTU updating part? That should never happen with TCP peers, and the old UDP code that caused it was removed (and if replaced, should be replaced with something that can reliably send messages with an arbitrary size).
|
||||||
func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) {
|
func (sinfo *sessionInfo) doRecv(p *wire_trafficPacket) {
|
||||||
defer util_putBytes(p.Payload)
|
defer util_putBytes(p.Payload)
|
||||||
payloadSize := uint16(len(p.Payload))
|
|
||||||
if !sinfo.nonceIsOK(&p.Nonce) {
|
if !sinfo.nonceIsOK(&p.Nonce) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bs, isOK := boxOpen(&sinfo.sharedSesKey, p.Payload, &p.Nonce)
|
bs, isOK := boxOpen(&sinfo.sharedSesKey, p.Payload, &p.Nonce)
|
||||||
if !isOK {
|
if !isOK {
|
||||||
// We're going to guess that the session MTU is too large
|
|
||||||
// Set myMTU to the largest value we think we can receive
|
|
||||||
fixSessionMTU := func() {
|
|
||||||
// This clamps down to 1280 almost immediately over ipv4
|
|
||||||
// Over link-local ipv6, it seems to approach link MTU
|
|
||||||
// So maybe it's doing the right thing?...
|
|
||||||
//sinfo.core.log.Println("DEBUG got bad packet:", payloadSize)
|
|
||||||
newMTU := payloadSize - boxOverhead
|
|
||||||
if newMTU < 1280 {
|
|
||||||
newMTU = 1280
|
|
||||||
}
|
|
||||||
if newMTU < sinfo.myMTU {
|
|
||||||
sinfo.myMTU = newMTU
|
|
||||||
sinfo.core.sessions.sendPingPong(sinfo, false)
|
|
||||||
sinfo.mtuTime = time.Now()
|
|
||||||
sinfo.wasMTUFixed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go func() { sinfo.core.router.admin <- fixSessionMTU }()
|
|
||||||
util_putBytes(bs)
|
util_putBytes(bs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fixSessionMTU := func() {
|
|
||||||
if time.Since(sinfo.mtuTime) > time.Minute {
|
|
||||||
sinfo.myMTU = uint16(sinfo.core.tun.mtu)
|
|
||||||
sinfo.mtuTime = time.Now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go func() { sinfo.core.router.admin <- fixSessionMTU }()
|
|
||||||
sinfo.updateNonce(&p.Nonce)
|
sinfo.updateNonce(&p.Nonce)
|
||||||
sinfo.time = time.Now()
|
sinfo.time = time.Now()
|
||||||
sinfo.bytesRecvd += uint64(len(bs))
|
sinfo.bytesRecvd += uint64(len(bs))
|
||||||
|
@ -364,7 +364,7 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
|
|||||||
doUpdate := false
|
doUpdate := false
|
||||||
if !equiv(&sender.locator, &oldSender.locator) {
|
if !equiv(&sender.locator, &oldSender.locator) {
|
||||||
doUpdate = true
|
doUpdate = true
|
||||||
//sender.firstSeen = now // TODO? uncomment to prevent flapping?
|
sender.firstSeen = now
|
||||||
}
|
}
|
||||||
t.data.peers[fromPort] = sender
|
t.data.peers[fromPort] = sender
|
||||||
updateRoot := false
|
updateRoot := false
|
||||||
@ -402,7 +402,16 @@ func (t *switchTable) unlockedHandleMsg(msg *switchMsg, fromPort switchPort) {
|
|||||||
updateRoot = true
|
updateRoot = true
|
||||||
case sender.port != t.parent: // do nothing
|
case sender.port != t.parent: // do nothing
|
||||||
case !equiv(&sender.locator, &t.data.locator):
|
case !equiv(&sender.locator, &t.data.locator):
|
||||||
updateRoot = true
|
// Special case
|
||||||
|
// If coords changed, then this may now be a worse parent than before
|
||||||
|
// Re-parent the node (de-parent and reprocess the message)
|
||||||
|
// Then reprocess *all* messages to look for a better parent
|
||||||
|
// This is so we don't keep using this node as our parent if there's something better
|
||||||
|
t.parent = 0
|
||||||
|
t.unlockedHandleMsg(msg, fromPort)
|
||||||
|
for _, info := range t.data.peers {
|
||||||
|
t.unlockedHandleMsg(&info.msg, info.port)
|
||||||
|
}
|
||||||
case now.Sub(t.time) < switch_throttle: // do nothing
|
case now.Sub(t.time) < switch_throttle: // do nothing
|
||||||
case sender.locator.tstamp > t.data.locator.tstamp:
|
case sender.locator.tstamp > t.data.locator.tstamp:
|
||||||
updateRoot = true
|
updateRoot = true
|
||||||
|
@ -60,29 +60,12 @@ func (iface *tcpInterface) getAddr() *net.TCPAddr {
|
|||||||
|
|
||||||
// Attempts to initiate a connection to the provided address.
|
// Attempts to initiate a connection to the provided address.
|
||||||
func (iface *tcpInterface) connect(addr string) {
|
func (iface *tcpInterface) connect(addr string) {
|
||||||
iface.call(addr)
|
iface.call(addr, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempst to initiate a connection to the provided address, viathe provided socks proxy address.
|
// Attempst to initiate a connection to the provided address, viathe provided socks proxy address.
|
||||||
func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) {
|
func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) {
|
||||||
// TODO make sure this doesn't keep attempting/killing connections when one is already active.
|
iface.call(peeraddr, &socksaddr)
|
||||||
// I think some of the interaction between this and callWithConn needs work, so the dial isn't even attempted if there's already an outgoing call to peeraddr.
|
|
||||||
// Or maybe only if there's already an outgoing call to peeraddr via this socksaddr?
|
|
||||||
go func() {
|
|
||||||
dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct)
|
|
||||||
if err == nil {
|
|
||||||
conn, err := dialer.Dial("tcp", peeraddr)
|
|
||||||
if err == nil {
|
|
||||||
iface.callWithConn(&wrappedConn{
|
|
||||||
c: conn,
|
|
||||||
raddr: &wrappedAddr{
|
|
||||||
network: "tcp",
|
|
||||||
addr: peeraddr,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the struct.
|
// Initializes the struct.
|
||||||
@ -112,33 +95,12 @@ func (iface *tcpInterface) listener() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by connectSOCKS, it's like call but with the connection already established.
|
|
||||||
func (iface *tcpInterface) callWithConn(conn net.Conn) {
|
|
||||||
go func() {
|
|
||||||
raddr := conn.RemoteAddr().String()
|
|
||||||
iface.mutex.Lock()
|
|
||||||
_, isIn := iface.calls[raddr]
|
|
||||||
iface.mutex.Unlock()
|
|
||||||
if !isIn {
|
|
||||||
iface.mutex.Lock()
|
|
||||||
iface.calls[raddr] = struct{}{}
|
|
||||||
iface.mutex.Unlock()
|
|
||||||
defer func() {
|
|
||||||
iface.mutex.Lock()
|
|
||||||
delete(iface.calls, raddr)
|
|
||||||
iface.mutex.Unlock()
|
|
||||||
}()
|
|
||||||
iface.handler(conn, false)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if a connection already exists.
|
// Checks if a connection already exists.
|
||||||
// If not, it adds it to the list of active outgoing calls (to block future attempts) and dials the address.
|
// If not, it adds it to the list of active outgoing calls (to block future attempts) and dials the address.
|
||||||
// If the dial is successful, it launches the handler.
|
// If the dial is successful, it launches the handler.
|
||||||
// When finished, it removes the outgoing call, so reconnection attempts can be made later.
|
// When finished, it removes the outgoing call, so reconnection attempts can be made later.
|
||||||
// This all happens in a separate goroutine that it spawns.
|
// This all happens in a separate goroutine that it spawns.
|
||||||
func (iface *tcpInterface) call(saddr string) {
|
func (iface *tcpInterface) call(saddr string, socksaddr *string) {
|
||||||
go func() {
|
go func() {
|
||||||
quit := false
|
quit := false
|
||||||
iface.mutex.Lock()
|
iface.mutex.Lock()
|
||||||
@ -153,13 +115,35 @@ func (iface *tcpInterface) call(saddr string) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
iface.mutex.Unlock()
|
iface.mutex.Unlock()
|
||||||
if !quit {
|
if quit {
|
||||||
conn, err := net.Dial("tcp", saddr)
|
return
|
||||||
|
}
|
||||||
|
var conn net.Conn
|
||||||
|
var err error
|
||||||
|
if socksaddr != nil {
|
||||||
|
var dialer proxy.Dialer
|
||||||
|
dialer, err = proxy.SOCKS5("tcp", *socksaddr, nil, proxy.Direct)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn, err = dialer.Dial("tcp", saddr)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn = &wrappedConn{
|
||||||
|
c: conn,
|
||||||
|
raddr: &wrappedAddr{
|
||||||
|
network: "tcp",
|
||||||
|
addr: saddr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conn, err = net.Dial("tcp", saddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
iface.handler(conn, false)
|
|
||||||
}
|
}
|
||||||
|
iface.handler(conn, false)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ func (tun *tunDevice) setupAddress(addr string) error {
|
|||||||
|
|
||||||
ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask))
|
ar.ifra_prefixmask.sin6_len = uint8(unsafe.Sizeof(ar.ifra_prefixmask))
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
binary.LittleEndian.PutUint16(b, uint16(0xFF00))
|
binary.LittleEndian.PutUint16(b, uint16(0xFE00))
|
||||||
ar.ifra_prefixmask.sin6_addr[0] = uint16(binary.BigEndian.Uint16(b))
|
ar.ifra_prefixmask.sin6_addr[0] = uint16(binary.BigEndian.Uint16(b))
|
||||||
|
|
||||||
ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr))
|
ar.ifra_addr.sin6_len = uint8(unsafe.Sizeof(ar.ifra_addr))
|
||||||
|
52
yggdrasil.go
52
yggdrasil.go
@ -1,24 +1,29 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "encoding/json"
|
import (
|
||||||
import "encoding/hex"
|
"bytes"
|
||||||
import "flag"
|
"encoding/hex"
|
||||||
import "fmt"
|
"encoding/json"
|
||||||
import "io/ioutil"
|
"flag"
|
||||||
import "os"
|
"fmt"
|
||||||
import "os/signal"
|
"io/ioutil"
|
||||||
import "syscall"
|
"log"
|
||||||
import "time"
|
"math/rand"
|
||||||
import "regexp"
|
"os"
|
||||||
import "math/rand"
|
"os/signal"
|
||||||
import "log"
|
"regexp"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
import "yggdrasil"
|
"golang.org/x/text/encoding/unicode"
|
||||||
import "yggdrasil/config"
|
|
||||||
|
|
||||||
import "github.com/kardianos/minwinsvc"
|
"github.com/kardianos/minwinsvc"
|
||||||
import "github.com/neilalexander/hjson-go"
|
"github.com/mitchellh/mapstructure"
|
||||||
import "github.com/mitchellh/mapstructure"
|
"github.com/neilalexander/hjson-go"
|
||||||
|
|
||||||
|
"yggdrasil"
|
||||||
|
"yggdrasil/config"
|
||||||
|
)
|
||||||
|
|
||||||
type nodeConfig = config.NodeConfig
|
type nodeConfig = config.NodeConfig
|
||||||
type Core = yggdrasil.Core
|
type Core = yggdrasil.Core
|
||||||
@ -107,6 +112,19 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
// If there's a byte order mark - which Windows 10 is now incredibly fond of
|
||||||
|
// throwing everywhere when it's converting things into UTF-16 for the hell
|
||||||
|
// of it - remove it and decode back down into UTF-8. This is necessary
|
||||||
|
// because hjson doesn't know what to do with UTF-16 and will panic
|
||||||
|
if bytes.Compare(config[0:2], []byte{0xFF, 0xFE}) == 0 ||
|
||||||
|
bytes.Compare(config[0:2], []byte{0xFF, 0xFF}) == 0 {
|
||||||
|
utf := unicode.UTF16(unicode.BigEndian, unicode.UseBOM)
|
||||||
|
decoder := utf.NewDecoder()
|
||||||
|
config, err = decoder.Bytes(config)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Generate a new configuration - this gives us a set of sane defaults -
|
// Generate a new configuration - this gives us a set of sane defaults -
|
||||||
// then parse the configuration we loaded above on top of it. The effect
|
// then parse the configuration we loaded above on top of it. The effect
|
||||||
// of this is that any configuration item that is missing from the provided
|
// of this is that any configuration item that is missing from the provided
|
||||||
|
Loading…
Reference in New Issue
Block a user