Browse Source

cloaking: Generate and check for cloak keys appropriately

devel+cloaks
Daniel Oaks 6 years ago
parent
commit
21a061c137
4 changed files with 170 additions and 74 deletions
  1. 53
    10
      irc/cloaking/cloak.go
  2. 3
    6
      irc/config.go
  3. 94
    58
      oragono.go
  4. 20
    0
      oragono.yaml

+ 53
- 10
irc/cloaking/cloak.go View File

@@ -6,7 +6,9 @@ package cloak
6 6
 
7 7
 import (
8 8
 	"crypto/hmac"
9
+	"crypto/rand"
9 10
 	"crypto/sha256"
11
+	"encoding/base64"
10 12
 	"errors"
11 13
 	"fmt"
12 14
 	"net"
@@ -28,7 +30,7 @@ var (
28 30
 	errNetName             = errors.New("NetName is not the right size (must be 1-10 characters long)")
29 31
 	errNotIPv4             = errors.New("The given address is not an IPv4 address")
30 32
 	errConfigDisabled      = errors.New("Config has disabled IP cloaking")
31
-	errKeysTooShort        = fmt.Errorf("Cloaking keys too short (min: %d)", MinKeyLength)
33
+	errKeysTooShort        = errors.New("Cloaking keys too short")
32 34
 	errKeysNotRandomEnough = errors.New("Cloaking keys aren't random enough")
33 35
 )
34 36
 
@@ -38,22 +40,63 @@ type Config struct {
38 40
 	Enabled bool
39 41
 	// NetName is the name used for the network in cloaked addresses.
40 42
 	NetName string
41
-	// IPv4KeyAString is used to cloak the `a` part of the IP address.
42
-	IPv4KeyAString string `yaml:"ipv4-key-a"`
43
+	// IPv4KeyString is used to cloak the `a`, `b`, `c` and `d` parts of the IP address.
44
+	// it is split up into the separate A/B/C/D keys below.
45
+	IPv4KeysString []string `yaml:"ipv4-keys"`
43 46
 	IPv4KeyA       []byte
44
-	// IPv4KeyBString is used to cloak the `b` part of the IP address.
45
-	IPv4KeyBString string `yaml:"ipv4-key-b"`
46 47
 	IPv4KeyB       []byte
47
-	// IPv4KeyCString is used to cloak the `c` part of the IP address.
48
-	IPv4KeyCString string `yaml:"ipv4-key-c"`
49 48
 	IPv4KeyC       []byte
50
-	// IPv4KeyDString is used to cloak the `d` part of the IP address.
51
-	IPv4KeyDString string `yaml:"ipv4-key-d"`
52 49
 	IPv4KeyD       []byte
53 50
 }
54 51
 
52
+// CheckConfig checks whether we're configured correctly.
53
+func (config *Config) CheckConfig() error {
54
+	if config.Enabled {
55
+		// IPv4 cloak keys
56
+		if len(config.IPv4KeysString) < 4 {
57
+			return errKeysTooShort
58
+		}
59
+
60
+		keyA, errA := base64.StdEncoding.DecodeString(config.IPv4KeysString[0])
61
+		keyB, errB := base64.StdEncoding.DecodeString(config.IPv4KeysString[1])
62
+		keyC, errC := base64.StdEncoding.DecodeString(config.IPv4KeysString[2])
63
+		keyD, errD := base64.StdEncoding.DecodeString(config.IPv4KeysString[3])
64
+
65
+		if errA != nil || errB != nil || errC != nil || errD != nil {
66
+			return fmt.Errorf("Could not decode IPv4 cloak keys")
67
+		}
68
+		if len(keyA) < MinKeyLength || len(keyB) < MinKeyLength || len(keyC) < MinKeyLength || len(keyD) < MinKeyLength {
69
+			return errKeysTooShort
70
+		}
71
+
72
+		config.IPv4KeyA = keyA
73
+		config.IPv4KeyB = keyB
74
+		config.IPv4KeyC = keyC
75
+		config.IPv4KeyD = keyD
76
+
77
+		// try cloaking IPs to confirm everything works properly
78
+		_, err := IPv4(net.ParseIP("8.8.8.8"), config)
79
+		if err != nil {
80
+			return err
81
+		}
82
+	}
83
+	return nil
84
+}
85
+
86
+// GenerateCloakKey generates one cloak key.
87
+func GenerateCloakKey() (string, error) {
88
+	keyBytes := make([]byte, MinKeyLength)
89
+	_, err := rand.Read(keyBytes)
90
+	if err != nil {
91
+		return "", fmt.Errorf("Could not generate random bytes for cloak key: %s", err.Error())
92
+	}
93
+
94
+	return base64.StdEncoding.EncodeToString(keyBytes), nil
95
+}
96
+
55 97
 // IsRandomEnough makes sure people are using keys that are random enough.
56 98
 func IsRandomEnough(key []byte) bool {
99
+	//TODO(dan): actually find out how to calc this
57 100
 	return true
58 101
 }
59 102
 
@@ -85,7 +128,7 @@ func hashOctet(key []byte, data string) string {
85 128
 // if you have 4.5.6.7 and 4.3.2.1 then the `a` part of those addresses will
86 129
 // be the same value. This ensures chanops can properly ban dodgy people as
87 130
 // they need to do so.
88
-func IPv4(address net.IP, config Config) (string, error) {
131
+func IPv4(address net.IP, config *Config) (string, error) {
89 132
 	if !config.Enabled {
90 133
 		return "", errConfigDisabled
91 134
 	}

+ 3
- 6
irc/config.go View File

@@ -11,7 +11,6 @@ import (
11 11
 	"fmt"
12 12
 	"io/ioutil"
13 13
 	"log"
14
-	"net"
15 14
 	"strings"
16 15
 	"time"
17 16
 
@@ -421,11 +420,9 @@ func LoadConfig(filename string) (config *Config, err error) {
421 420
 			return nil, fmt.Errorf("STS port is incorrect, should be 0 if disabled: %d", config.Server.STS.Port)
422 421
 		}
423 422
 	}
424
-	if config.Network.IPCloaking.Enabled {
425
-		_, err := cloak.IPv4(net.ParseIP("8.8.8.8"), config.Network.IPCloaking)
426
-		if err != nil {
427
-			return nil, fmt.Errorf("IPv4 cloaking config is incorrect: %s", err.Error())
428
-		}
423
+	err = config.Network.IPCloaking.CheckConfig()
424
+	if err != nil {
425
+		return nil, fmt.Errorf("Could not parse IP cloaking: %s", err.Error())
429 426
 	}
430 427
 	if config.Server.ConnectionThrottle.Enabled {
431 428
 		config.Server.ConnectionThrottle.Duration, err = time.ParseDuration(config.Server.ConnectionThrottle.DurationString)

+ 94
- 58
oragono.go View File

@@ -13,10 +13,6 @@ import (
13 13
 	"syscall"
14 14
 	"time"
15 15
 
16
-	"net"
17
-
18
-	"encoding/base64"
19
-
20 16
 	"github.com/docopt/docopt-go"
21 17
 	"github.com/oragono/oragono/irc"
22 18
 	cloak "github.com/oragono/oragono/irc/cloaking"
@@ -33,6 +29,7 @@ Usage:
33 29
 	oragono initdb [--conf <filename>] [--quiet]
34 30
 	oragono upgradedb [--conf <filename>] [--quiet]
35 31
 	oragono genpasswd [--conf <filename>] [--quiet]
32
+	oragono genkeys
36 33
 	oragono mkcerts [--conf <filename>] [--quiet]
37 34
 	oragono run [--conf <filename>] [--quiet]
38 35
 	oragono -h | --help
@@ -43,57 +40,37 @@ Options:
43 40
 	-h --help          Show this screen.
44 41
 	--version          Show version.`
45 42
 
46
-	keyA, _ := base64.StdEncoding.DecodeString("idXACDbEhqRZsExn0jOTi4rtC6MrKBOcN4edxdSzTAA=")
47
-	keyB, _ := base64.StdEncoding.DecodeString("qODtg8WEJ0YA6JRnryDDUEoSdJyrGgPFI6hPNnGHyIw=")
48
-	keyC, _ := base64.StdEncoding.DecodeString("Oxqc6uDsyEO5vZcxHmtZ1zOLL8wwATeYA4KqJmkTJQo=")
49
-	keyD, _ := base64.StdEncoding.DecodeString("vd2eimWWh3L9fukFwxZThJ9pKTf/I5UZ/k7o/3JHkMc=")
50
-
51
-	conf := cloak.Config{
52
-		Enabled:  true,
53
-		NetName:  "Test",
54
-		IPv4KeyA: keyA,
55
-		IPv4KeyB: keyB,
56
-		IPv4KeyC: keyC,
57
-		IPv4KeyD: keyD,
58
-	}
59
-	ip := net.ParseIP("8.8.8.8")
60
-	key, err := cloak.IPv4(ip, conf)
61
-	fmt.Println(ip, key, err)
62
-	ip = net.ParseIP("9.4.8.8")
63
-	key, err = cloak.IPv4(ip, conf)
64
-	fmt.Println(ip, key, err)
65
-	ip = net.ParseIP("8.4.2.8")
66
-	key, err = cloak.IPv4(ip, conf)
67
-	fmt.Println(ip, key, err)
68
-	ip = net.ParseIP("8.4.2.1")
69
-	key, err = cloak.IPv4(ip, conf)
70
-	fmt.Println(ip, key, err)
71
-
72 43
 	arguments, _ := docopt.Parse(usage, nil, true, version, false)
73 44
 
45
+	// load config and logger for everything but genkeys
46
+	var err error
74 47
 	configfile := arguments["--conf"].(string)
75
-	config, err := irc.LoadConfig(configfile)
76
-	if err != nil {
77
-		log.Fatal("Config file did not load successfully:", err.Error())
78
-	}
48
+	var config *irc.Config
49
+	var logman *logger.Manager
50
+	if !arguments["genkeys"].(bool) {
51
+		config, err = irc.LoadConfig(configfile)
52
+		if err != nil {
53
+			log.Fatal("Config file did not load successfully:", err.Error())
54
+		}
79 55
 
80
-	// assemble separate log configs
81
-	var logConfigs []logger.Config
82
-	for _, lConfig := range config.Logging {
83
-		logConfigs = append(logConfigs, logger.Config{
84
-			MethodStdout:  lConfig.MethodStdout,
85
-			MethodStderr:  lConfig.MethodStderr,
86
-			MethodFile:    lConfig.MethodFile,
87
-			Filename:      lConfig.Filename,
88
-			Level:         lConfig.Level,
89
-			Types:         lConfig.Types,
90
-			ExcludedTypes: lConfig.ExcludedTypes,
91
-		})
92
-	}
56
+		// assemble separate log configs
57
+		var logConfigs []logger.Config
58
+		for _, lConfig := range config.Logging {
59
+			logConfigs = append(logConfigs, logger.Config{
60
+				MethodStdout:  lConfig.MethodStdout,
61
+				MethodStderr:  lConfig.MethodStderr,
62
+				MethodFile:    lConfig.MethodFile,
63
+				Filename:      lConfig.Filename,
64
+				Level:         lConfig.Level,
65
+				Types:         lConfig.Types,
66
+				ExcludedTypes: lConfig.ExcludedTypes,
67
+			})
68
+		}
93 69
 
94
-	logger, err := logger.NewManager(logConfigs...)
95
-	if err != nil {
96
-		log.Fatal("Logger did not load successfully:", err.Error())
70
+		logman, err = logger.NewManager(logConfigs...)
71
+		if err != nil {
72
+			log.Fatal("Logger did not load successfully:", err.Error())
73
+		}
97 74
 	}
98 75
 
99 76
 	if arguments["genpasswd"].(bool) {
@@ -109,6 +86,65 @@ Options:
109 86
 		}
110 87
 		fmt.Print("\n")
111 88
 		fmt.Println(encoded)
89
+	} else if arguments["genkeys"].(bool) {
90
+		fmt.Println("Here are your cloak keys:")
91
+
92
+		// generate IPv4 keys
93
+		keyA, err := cloak.GenerateCloakKey()
94
+		if err != nil {
95
+			log.Fatal("Error generating cloak keys:", err)
96
+		}
97
+		keyB, err := cloak.GenerateCloakKey()
98
+		if err != nil {
99
+			log.Fatal("Error generating cloak keys:", err)
100
+		}
101
+		keyC, err := cloak.GenerateCloakKey()
102
+		if err != nil {
103
+			log.Fatal("Error generating cloak keys:", err)
104
+		}
105
+		keyD, err := cloak.GenerateCloakKey()
106
+		if err != nil {
107
+			log.Fatal("Error generating cloak keys:", err)
108
+		}
109
+
110
+		fmt.Println(fmt.Sprintf(`ipv4-keys: ["%s", "%s", "%s", "%s"]`, keyA, keyB, keyC, keyD))
111
+
112
+		// generate IPv6 keys
113
+		keyA, err = cloak.GenerateCloakKey()
114
+		if err != nil {
115
+			log.Fatal("Error generating cloak keys:", err)
116
+		}
117
+		keyB, err = cloak.GenerateCloakKey()
118
+		if err != nil {
119
+			log.Fatal("Error generating cloak keys:", err)
120
+		}
121
+		keyC, err = cloak.GenerateCloakKey()
122
+		if err != nil {
123
+			log.Fatal("Error generating cloak keys:", err)
124
+		}
125
+		keyD, err = cloak.GenerateCloakKey()
126
+		if err != nil {
127
+			log.Fatal("Error generating cloak keys:", err)
128
+		}
129
+		keyE, err := cloak.GenerateCloakKey()
130
+		if err != nil {
131
+			log.Fatal("Error generating cloak keys:", err)
132
+		}
133
+		keyF, err := cloak.GenerateCloakKey()
134
+		if err != nil {
135
+			log.Fatal("Error generating cloak keys:", err)
136
+		}
137
+		keyG, err := cloak.GenerateCloakKey()
138
+		if err != nil {
139
+			log.Fatal("Error generating cloak keys:", err)
140
+		}
141
+		keyH, err := cloak.GenerateCloakKey()
142
+		if err != nil {
143
+			log.Fatal("Error generating cloak keys:", err)
144
+		}
145
+
146
+		fmt.Println(fmt.Sprintf(`ipv6-keys: ["%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s"]`, keyA, keyB, keyC, keyD, keyE, keyF, keyG, keyH))
147
+
112 148
 	} else if arguments["initdb"].(bool) {
113 149
 		irc.InitDB(config.Datastore.Path)
114 150
 		if !arguments["--quiet"].(bool) {
@@ -139,13 +175,13 @@ Options:
139 175
 	} else if arguments["run"].(bool) {
140 176
 		rand.Seed(time.Now().UTC().UnixNano())
141 177
 		if !arguments["--quiet"].(bool) {
142
-			logger.Info("startup", fmt.Sprintf("Oragono v%s starting", irc.SemVer))
178
+			logman.Info("startup", fmt.Sprintf("Oragono v%s starting", irc.SemVer))
143 179
 		}
144 180
 
145 181
 		// profiling
146 182
 		if config.Debug.StackImpact.Enabled {
147 183
 			if config.Debug.StackImpact.AgentKey == "" || config.Debug.StackImpact.AppName == "" {
148
-				logger.Error("startup", "Could not start StackImpact - agent-key or app-name are undefined")
184
+				logman.Error("startup", "Could not start StackImpact - agent-key or app-name are undefined")
149 185
 				return
150 186
 			}
151 187
 
@@ -153,22 +189,22 @@ Options:
153 189
 			agent.Start(stackimpact.Options{AgentKey: config.Debug.StackImpact.AgentKey, AppName: config.Debug.StackImpact.AppName})
154 190
 			defer agent.RecordPanic()
155 191
 
156
-			logger.Info("startup", fmt.Sprintf("StackImpact profiling started as %s", config.Debug.StackImpact.AppName))
192
+			logman.Info("startup", fmt.Sprintf("StackImpact profiling started as %s", config.Debug.StackImpact.AppName))
157 193
 		}
158 194
 
159 195
 		// warning if running a non-final version
160 196
 		if strings.Contains(irc.SemVer, "unreleased") {
161
-			logger.Warning("startup", "You are currently running an unreleased beta version of Oragono that may be unstable and could corrupt your database.\nIf you are running a production network, please download the latest build from https://oragono.io/downloads.html and run that instead.")
197
+			logman.Warning("startup", "You are currently running an unreleased beta version of Oragono that may be unstable and could corrupt your database.\nIf you are running a production network, please download the latest build from https://oragono.io/downloads.html and run that instead.")
162 198
 		}
163 199
 
164
-		server, err := irc.NewServer(configfile, config, logger)
200
+		server, err := irc.NewServer(configfile, config, logman)
165 201
 		if err != nil {
166
-			logger.Error("startup", fmt.Sprintf("Could not load server: %s", err.Error()))
202
+			logman.Error("startup", fmt.Sprintf("Could not load server: %s", err.Error()))
167 203
 			return
168 204
 		}
169 205
 		if !arguments["--quiet"].(bool) {
170
-			logger.Info("startup", "Server running")
171
-			defer logger.Info("shutdown", fmt.Sprintf("Oragono v%s exiting", irc.SemVer))
206
+			logman.Info("startup", "Server running")
207
+			defer logman.Info("shutdown", fmt.Sprintf("Oragono v%s exiting", irc.SemVer))
172 208
 		}
173 209
 		server.Run()
174 210
 	}

+ 20
- 0
oragono.yaml View File

@@ -5,6 +5,26 @@ network:
5 5
     # name of the network
6 6
     name: OragonoTest
7 7
 
8
+    # cloaking IP addresses and hostnames
9
+    ip-cloaking:
10
+        # enable the cloaking
11
+        enabled: false
12
+
13
+        # short name to use in cloaked hostnames
14
+        netname: "testnet"
15
+
16
+        # ipv4 cloak keys
17
+        # to generate these keys, run "oragono genkeys"
18
+        ipv4-keys: ["keyhere", "keyhere", "keyhere", "keyhere"]
19
+
20
+        # ipv6 cloak keys
21
+        # to generate these keys, run "oragono genkeys"
22
+        ipv6-keys: ["keyhere", "keyhere", "keyhere", "keyhere", "keyhere", "keyhere", "keyhere", "keyhere"]
23
+
24
+        # hostname cloaking keys
25
+        # to generate these keys, run "oragono genkeys"
26
+        hostname-keys: ["keyhere", "keyhere", "keyhere", "keyhere"]
27
+
8 28
 # server configuration
9 29
 server:
10 30
     # server name

Loading…
Cancel
Save