2020-02-28 00:22:32 +01:00
|
|
|
package dsnet
|
|
|
|
|
|
|
|
import (
|
2020-03-01 22:39:05 +01:00
|
|
|
"fmt"
|
2020-03-02 23:31:52 +01:00
|
|
|
"io/ioutil"
|
2020-03-02 00:08:10 +01:00
|
|
|
"math/rand"
|
|
|
|
"net"
|
2020-03-02 23:31:52 +01:00
|
|
|
"net/http"
|
2020-03-03 23:33:48 +01:00
|
|
|
"os"
|
2020-03-02 22:11:45 +01:00
|
|
|
"strings"
|
2020-03-01 22:39:05 +01:00
|
|
|
"time"
|
2020-02-28 00:22:32 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func Init() {
|
2020-03-03 23:33:48 +01:00
|
|
|
_, err := os.Stat(CONFIG_FILE)
|
|
|
|
|
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
ExitFail("Refusing to overwrite existing %s", CONFIG_FILE)
|
|
|
|
}
|
|
|
|
|
2020-03-01 22:39:05 +01:00
|
|
|
conf := DsnetConfig{
|
2020-03-06 00:56:24 +01:00
|
|
|
PrivateKey: GenerateJSONPrivateKey(),
|
2020-03-04 20:38:48 +01:00
|
|
|
ListenPort: DEFAULT_LISTEN_PORT,
|
2020-10-25 09:05:56 +01:00
|
|
|
Network: getPrivateNet(),
|
2020-10-25 11:06:25 +01:00
|
|
|
Network6: getULANet(),
|
2020-03-04 20:47:27 +01:00
|
|
|
Peers: []PeerConfig{},
|
2020-03-04 20:38:48 +01:00
|
|
|
Domain: "dsnet",
|
|
|
|
ReportFile: DEFAULT_REPORT_FILE,
|
|
|
|
ExternalIP: getExternalIP(),
|
2020-10-26 09:27:22 +01:00
|
|
|
ExternalIP6: getExternalIP6(),
|
2020-03-04 20:38:48 +01:00
|
|
|
InterfaceName: DEFAULT_INTERFACE_NAME,
|
2020-03-08 21:48:10 +01:00
|
|
|
Networks: []JSONIPNet{},
|
2020-03-01 21:54:33 +01:00
|
|
|
}
|
2020-03-01 22:39:05 +01:00
|
|
|
|
2020-10-25 15:57:18 +01:00
|
|
|
conf.IP = conf.MustAllocateIP()
|
|
|
|
conf.IP6 = conf.MustAllocateIP6()
|
2020-10-25 09:23:43 +01:00
|
|
|
|
2020-03-16 20:29:16 +01:00
|
|
|
// DNS not set by default
|
|
|
|
//conf.DNS = IP
|
2020-03-02 21:10:48 +01:00
|
|
|
|
2020-03-02 03:54:43 +01:00
|
|
|
conf.MustSave()
|
2020-03-01 22:48:24 +01:00
|
|
|
|
2020-10-25 09:07:43 +01:00
|
|
|
fmt.Printf("Config written to %s. Please check/edit.\n", CONFIG_FILE)
|
2020-03-01 21:54:33 +01:00
|
|
|
}
|
|
|
|
|
2020-10-25 09:05:56 +01:00
|
|
|
// get a random IPv4 /22 subnet on 10.0.0.0 (1023 hosts) (or /24?)
|
|
|
|
func getPrivateNet() JSONIPNet {
|
2020-03-01 22:39:05 +01:00
|
|
|
rbs := make([]byte, 2)
|
|
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
|
|
rand.Read(rbs)
|
|
|
|
|
2020-03-01 23:29:11 +01:00
|
|
|
return JSONIPNet{
|
2020-03-02 00:17:01 +01:00
|
|
|
IPNet: net.IPNet{
|
2020-03-02 00:08:10 +01:00
|
|
|
net.IP{10, rbs[0], rbs[1] << 2, 0},
|
|
|
|
net.IPMask{255, 255, 252, 0},
|
2020-03-01 23:03:31 +01:00
|
|
|
},
|
2020-03-01 21:54:33 +01:00
|
|
|
}
|
2020-02-28 00:22:32 +01:00
|
|
|
}
|
2020-03-02 22:11:45 +01:00
|
|
|
|
2020-10-25 11:06:25 +01:00
|
|
|
func getULANet() JSONIPNet {
|
2020-10-25 09:05:56 +01:00
|
|
|
rbs := make([]byte, 5)
|
|
|
|
rand.Seed(time.Now().UTC().UnixNano())
|
|
|
|
rand.Read(rbs)
|
|
|
|
|
|
|
|
// fc00 prefix with 40 bit global id and zero (16 bit) subnet ID
|
|
|
|
return JSONIPNet{
|
|
|
|
IPNet: net.IPNet{
|
2020-10-25 16:15:46 +01:00
|
|
|
net.IP{0xfd, 0, rbs[0], rbs[1], rbs[2], rbs[3], rbs[4], 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
2020-10-25 09:05:56 +01:00
|
|
|
net.IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-26 09:27:22 +01:00
|
|
|
// TODO factor getExternalIP + getExternalIP6
|
2020-03-02 22:11:45 +01:00
|
|
|
func getExternalIP() net.IP {
|
2020-10-26 09:27:22 +01:00
|
|
|
var IP net.IP
|
|
|
|
// arbitrary external IP is used (one that's guaranteed to route outside.
|
|
|
|
// In this case, Google's DNS server. Doesn't actually need to be online.)
|
|
|
|
conn, err := net.Dial("udp", "8.8.8.8:53")
|
|
|
|
if err != nil {
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
|
|
localAddr := conn.LocalAddr().String()
|
|
|
|
IP = net.ParseIP(strings.Split(localAddr, ":")[0])
|
|
|
|
IP = IP.To4()
|
|
|
|
|
|
|
|
if !(IP[0] == 10 || (IP[0] == 172 && IP[1] >= 16 && IP[1] <= 31) || (IP[0] == 192 && IP[1] == 168)) {
|
|
|
|
// not private, so public
|
|
|
|
return IP
|
|
|
|
}
|
2020-03-02 22:36:41 +01:00
|
|
|
}
|
2020-03-02 23:31:52 +01:00
|
|
|
|
|
|
|
// detect private IP and use icanhazip.com instead
|
|
|
|
client := http.Client{
|
|
|
|
Timeout: 5 * time.Second,
|
|
|
|
}
|
|
|
|
resp, err := client.Get("https://ipv4.icanhazip.com/")
|
|
|
|
check(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode == http.StatusOK {
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
check(err)
|
|
|
|
IP = net.ParseIP(strings.TrimSpace(string(body)))
|
|
|
|
return IP.To4()
|
|
|
|
}
|
|
|
|
|
2020-03-02 22:36:41 +01:00
|
|
|
return net.IP{}
|
2020-03-02 22:11:45 +01:00
|
|
|
}
|
2020-10-26 09:27:22 +01:00
|
|
|
|
|
|
|
func getExternalIP6() net.IP {
|
|
|
|
var IP net.IP
|
|
|
|
conn, err := net.Dial("udp", "2001:4860:4860::8888:53")
|
|
|
|
if err != nil {
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
|
|
localAddr := conn.LocalAddr().String()
|
|
|
|
IP = net.ParseIP(strings.Split(localAddr, ":")[0])
|
|
|
|
return IP
|
|
|
|
}
|
|
|
|
|
|
|
|
client := http.Client{
|
|
|
|
Timeout: 5 * time.Second,
|
|
|
|
}
|
|
|
|
resp, err := client.Get("https://ipv6.icanhazip.com/")
|
|
|
|
check(err)
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode == http.StatusOK {
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
|
check(err)
|
|
|
|
IP = net.ParseIP(strings.TrimSpace(string(body)))
|
|
|
|
return IP
|
|
|
|
}
|
|
|
|
|
|
|
|
return net.IP{}
|
|
|
|
}
|