diff --git a/caddy.go b/caddy.go
index c5ff88ca0..3d8a6139b 100644
--- a/caddy.go
+++ b/caddy.go
@@ -763,6 +763,35 @@ func IsLoopback(addr string) bool {
 		strings.HasPrefix(host, "127.")
 }
 
+// IsInternal returns true if the IP of addr
+// belongs to a private network IP range. addr must only
+// be an IP or an IP:port combination.
+// Loopback addresses are considered false.
+func IsInternal(addr string) bool {
+	private_networks := []string{
+		"10.0.0.0/8",
+		"172.16.0.0/12",
+		"192.168.0.0/16",
+		"fc00::/7",
+	}
+
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		host = addr // happens if the addr is just a hostname
+	}
+	ip := net.ParseIP(host)
+	if ip == nil {
+		return false
+	}
+	for _, private_network := range private_networks {
+		_, ipnet, _ := net.ParseCIDR(private_network)
+		if ipnet.Contains(ip) {
+			return true
+		}
+	}
+	return false
+}
+
 // Upgrade re-launches the process, preserving the listeners
 // for a graceful restart. It does NOT load new configuration;
 // it only starts the process anew with a fresh binary.
diff --git a/caddy_test.go b/caddy_test.go
index 61bb553e3..2f86105b0 100644
--- a/caddy_test.go
+++ b/caddy_test.go
@@ -61,6 +61,65 @@ func TestIsLoopback(t *testing.T) {
 	}
 }
 
+func TestIsInternal(t *testing.T) {
+	for i, test := range []struct {
+		input  string
+		expect bool
+	}{
+		{"9.255.255.255", false},
+		{"10.0.0.0", true},
+		{"10.0.0.1", true},
+		{"10.255.255.254", true},
+		{"10.255.255.255", true},
+		{"11.0.0.0", false},
+		{"10.0.0.5:1234", true},
+		{"11.0.0.5:1234", false},
+
+		{"172.15.255.255", false},
+		{"172.16.0.0", true},
+		{"172.16.0.1", true},
+		{"172.31.255.254", true},
+		{"172.31.255.255", true},
+		{"172.32.0.0", false},
+		{"172.16.0.1:1234", true},
+
+		{"192.167.255.255", false},
+		{"192.168.0.0", true},
+		{"192.168.0.1", true},
+		{"192.168.255.254", true},
+		{"192.168.255.255", true},
+		{"192.169.0.0", false},
+		{"192.168.0.1:1234", true},
+
+		{"fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", false},
+		{"fc00::", true},
+		{"fc00::1", true},
+		{"fdff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", true},
+		{"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", true},
+		{"fe00::", false},
+		{"fd12:3456:789a:1::1:1234", true},
+
+		{"example.com", false},
+		{"localhost", false},
+		{"localhost:1234", false},
+		{"localhost:", false},
+		{"127.0.0.1", false},
+		{"127.0.0.1:443", false},
+		{"127.0.1.5", false},
+		{"12.7.0.1", false},
+		{"[::1]", false},
+		{"[::1]:1234", false},
+		{"::1", false},
+		{"::", false},
+		{"[::]", false},
+		{"local", false},
+	} {
+		if got, want := IsInternal(test.input), test.expect; got != want {
+			t.Errorf("Test %d (%s): expected %v but was %v", i, test.input, want, got)
+		}
+	}
+}
+
 func TestListenerAddrEqual(t *testing.T) {
 	ln1, err := net.Listen("tcp", "[::]:0")
 	if err != nil {
diff --git a/caddytls/client.go b/caddytls/client.go
index 394c36882..deb94af7a 100644
--- a/caddytls/client.go
+++ b/caddytls/client.go
@@ -61,7 +61,7 @@ var newACMEClient = func(config *Config, allowPrompts bool) (*ACMEClient, error)
 	if err != nil {
 		return nil, err
 	}
-	if u.Scheme != "https" && !caddy.IsLoopback(u.Host) && !strings.HasPrefix(u.Host, "10.") {
+	if u.Scheme != "https" && !caddy.IsLoopback(u.Host) && !caddy.IsInternal(u.Host) {
 		return nil, fmt.Errorf("%s: insecure CA URL (HTTPS required)", caURL)
 	}