Browse Source

Automatically select network interface to listen on.

Peter Valdez 4 years ago
parent
commit
3964f9c6d8
1 changed files with 90 additions and 67 deletions
  1. 90 67
      secret.go

+ 90 - 67
secret.go

@@ -17,6 +17,7 @@ import (
17 17
 	"os"
18 18
 	"os/user"
19 19
 	"strconv"
20
+	"strings"
20 21
 )
21 22
 
22 23
 // General values
@@ -34,6 +35,10 @@ var entity *openpgp.Entity
34 35
 var entityList openpgp.EntityList
35 36
 var secretKeyring, publicKeyring string
36 37
 
38
+// Convenience
39
+var InternalAddrs []string
40
+var InvalidPrefixes []string
41
+
37 42
 // Flags
38 43
 var Flags = []cli.Flag{
39 44
 	cli.BoolFlag{
@@ -96,8 +101,12 @@ func receive() error {
96 101
 		return err
97 102
 	}
98 103
 
99
-	// Have the user select the IP address
100
-	ips, err := selectIPs()
104
+	// Get the interface and IPs that'll be used
105
+	iface, err := autoSelectInterface()
106
+	if err != nil {
107
+		return err
108
+	}
109
+	ips, err := getIPsFromInterface(iface, true)
101 110
 	if err != nil {
102 111
 		return err
103 112
 	}
@@ -110,11 +119,11 @@ func receive() error {
110 119
 		return err
111 120
 	}
112 121
 
113
-	server, _ := mdns.NewServer(&mdns.Config{Zone: service})
122
+	server, _ := mdns.NewServer(&mdns.Config{Zone: service, Iface: &iface})
114 123
 	defer server.Shutdown()
115 124
 
116 125
 	// Run the kite
117
-	fmt.Println("\nWaiting for secrets...")
126
+	fmt.Println("Waiting for secrets...")
118 127
 	k.Run()
119 128
 
120 129
 	return nil
@@ -148,6 +157,72 @@ func secret(r *kite.Request) (interface{}, error) {
148 157
 	return "Received.", nil
149 158
 }
150 159
 
160
+// Return true if s is prefixed by any of the prefixes
161
+func prefixedByAny(s string, prefixes []string) bool {
162
+	for _, prefix := range prefixes {
163
+		if strings.HasPrefix(s, prefix) {
164
+			return true
165
+		}
166
+	}
167
+	return false
168
+}
169
+
170
+func getIPsFromInterface(iface net.Interface, ignoreInternal bool) ([]net.IP, error) {
171
+	// Get the addresses
172
+	addrs, err := iface.Addrs()
173
+	if err != nil {
174
+		return nil, err
175
+	}
176
+
177
+	// Get the IPs from the Addrs
178
+	ips := make([]net.IP, 0, len(addrs))
179
+	for _, addr := range addrs {
180
+		// Ignore internal addresses
181
+		if ignoreInternal && prefixedByAny(addr.String(), InternalAddrs) {
182
+			continue
183
+		}
184
+
185
+		// Convert to IP
186
+		ip, _, err := net.ParseCIDR(addr.String())
187
+		if err != nil {
188
+			return nil, err
189
+		}
190
+		ips = append(ips, ip)
191
+	}
192
+
193
+	return ips, nil
194
+}
195
+
196
+func autoSelectInterface() (net.Interface, error) {
197
+	// Get the interfaces
198
+	allInterfaces, err := net.Interfaces()
199
+	if err != nil {
200
+		return net.Interface{}, err
201
+	}
202
+
203
+	// Get the list of addressable IPs
204
+	for _, iface := range allInterfaces {
205
+		// Ignore certain interfaces
206
+		if prefixedByAny(iface.Name, InvalidPrefixes) {
207
+			continue
208
+		}
209
+
210
+		// Get the interface IPs
211
+		ips, err := getIPsFromInterface(iface, true)
212
+		if err != nil {
213
+			return net.Interface{}, err
214
+		}
215
+
216
+		// Return if any valid IPs retrieved
217
+		if len(ips) > 0 {
218
+			return iface, nil
219
+		}
220
+	}
221
+
222
+	err = errors.New("Unable to automatically choose an IP address.")
223
+	return net.Interface{}, err
224
+}
225
+
151 226
 func selectIPs() ([]net.IP, error) {
152 227
 	// Get the interfaces
153 228
 	allInterfaces, err := net.Interfaces()
@@ -156,7 +231,7 @@ func selectIPs() ([]net.IP, error) {
156 231
 	}
157 232
 
158 233
 	// Filter out the ones with no addresses
159
-	ifaces := make([]net.Interface, 0)
234
+	choices := make([]net.Interface, 0, 4)
160 235
 	for _, iface := range allInterfaces {
161 236
 		// Get the addresses
162 237
 		addrs, err := iface.Addrs()
@@ -166,49 +241,25 @@ func selectIPs() ([]net.IP, error) {
166 241
 
167 242
 		// The interface is a valid choice if it has addresses
168 243
 		if len(addrs) > 0 {
169
-			ifaces = append(ifaces, iface)
244
+			choices = append(choices, iface)
170 245
 		}
171 246
 	}
172 247
 
173 248
 	// Error if there are no interfaces
174
-	if len(ifaces) == 0 {
249
+	if len(choices) == 0 {
175 250
 		err = errors.New("No interfaces with addresses to listen on.")
176 251
 		return nil, err
177 252
 	}
178 253
 
179
-	// Parse the addresses
180
-	choices := make([]net.Interface, len(ifaces))
181
-	for i, iface := range ifaces {
182
-		choices[i] = iface
183
-	}
184
-
185 254
 	// Display the choices
186
-	fmt.Println("= Your network interfaces =")
255
+	fmt.Println("- Your network interfaces -")
187 256
 	for i, choice := range choices {
188
-		// Get addresses
189
-		addrs, err := choice.Addrs()
257
+		ips, err := getIPsFromInterface(choice, false)
190 258
 		if err != nil {
191 259
 			return nil, err
192 260
 		}
193 261
 
194
-		// Skip if there are no addresses on this
195
-		if len(ifaces) == 0 {
196
-			err = errors.New("No interfaces to listen on.")
197
-			return nil, err
198
-		}
199
-
200
-		// Get the IP
201
-		ips := make([]net.IP, len(addrs))
202
-		for i, addr := range addrs {
203
-			ip, _, err := net.ParseCIDR(addr.String())
204
-			if err != nil {
205
-				return nil, err
206
-			}
207
-			ips[i] = ip
208
-		}
209
-
210
-		// Display the addresses
211
-		fmt.Println(strconv.Itoa(i), "-", ips)
262
+		fmt.Println(strconv.Itoa(i), "-", choice.Name, ips)
212 263
 	}
213 264
 
214 265
 	// Gather the user's input
@@ -223,43 +274,11 @@ func selectIPs() ([]net.IP, error) {
223 274
 	}
224 275
 
225 276
 	// Get the interface addresses
226
-	chosenInterface := choices[choice]
227
-	addrs, err := chosenInterface.Addrs()
277
+	ips, err := getIPsFromInterface(choices[choice], false)
228 278
 	if err != nil {
229 279
 		return nil, err
230 280
 	}
231 281
 
232
-	// Convert Addrs to IPs
233
-	ips := make([]net.IP, len(addrs))
234
-	for i, addr := range addrs {
235
-		ip, _, err := net.ParseCIDR(addr.String())
236
-		if err != nil {
237
-			return nil, err
238
-		}
239
-		ips[i] = ip
240
-	}
241
-
242
-	return ips, nil
243
-}
244
-
245
-func getIPs() ([]net.IP, error) {
246
-	// Get the string interface addresses
247
-	addrs, err := net.InterfaceAddrs()
248
-	if err != nil {
249
-		return nil, err
250
-	}
251
-
252
-	// Convert them to actual IP objects
253
-	ips := make([]net.IP, 0, 4)
254
-	for _, addr := range addrs {
255
-		ip, _, err := net.ParseCIDR(addr.String())
256
-		if err != nil {
257
-			return nil, err
258
-		}
259
-
260
-		ips = append(ips, ip)
261
-	}
262
-
263 282
 	return ips, nil
264 283
 }
265 284
 
@@ -408,6 +427,10 @@ func main() {
408 427
 	secretKeyring = fmt.Sprintf("%s/.gnupg/secring.gpg", prefix)
409 428
 	publicKeyring = fmt.Sprintf("%s/.gnupg/pubring.gpg", prefix)
410 429
 
430
+	// Setup the convenience values
431
+	InvalidPrefixes = []string{"docker", "vbox", "awdl"}
432
+	InternalAddrs = []string{"127.0.0.1/8", "fe80::1/64", "::1/128"}
433
+
411 434
 	// Setup the app
412 435
 	app := cli.NewApp()
413 436
 	app.Name = Name