Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
507d75829f | ||
|
|
83b97ad538 | ||
|
|
715cb772e7 | ||
|
|
b4c098890c |
No files matched your search
@@ -162,6 +162,11 @@ All notable changes to Housecarl are documented here. The format follows
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- An IPv4-mapped prefix (`::ffff:0:0/96`) is refused with an error that
|
||||||
|
says so; it was refused as "has host bits set; the prefix is invalid
|
||||||
|
Prefix".
|
||||||
|
- `hc forward show` shows the forward's hits and comment, and its
|
||||||
|
hairpin as `no`, `yes` or `yes, from …` (it printed `no -`).
|
||||||
- A history entry's ruleset diff showed the object it changed as moved:
|
- A history entry's ruleset diff showed the object it changed as moved:
|
||||||
stepping back put the old form at the end of its list, so updating
|
stepping back put the old form at the end of its list, so updating
|
||||||
one port forward (turning hairpin off) also showed its forward and
|
one port forward (turning hairpin off) also showed its forward and
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ The web UI is on `http://127.0.0.1:8070/` (see `listen` in
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Housecarl 0.2.0 is in testing (0.2.0-rc.4): zones, address sets and
|
Housecarl 0.2.0 is in testing (0.2.0-rc.4+git70-83b97ad): zones, address sets and
|
||||||
services with ordered rules, IPv4 and IPv6, port forwards with hairpin NAT
|
services with ordered rules, IPv4 and IPv6, port forwards with hairpin NAT
|
||||||
and IPv6 pinholes, source NAT and redirects, built-ins, probation for
|
and IPv6 pinholes, source NAT and redirects, built-ins, probation for
|
||||||
network changes (confirmed by the client that made them), the ruleset
|
network changes (confirmed by the client that made them), the ruleset
|
||||||
|
|||||||
+10
-1
@@ -605,7 +605,16 @@ func forwardCmd() *cobra.Command {
|
|||||||
if f.ToPort != "" {
|
if f.ToPort != "" {
|
||||||
fmt.Fprintf(w, "To port:\t%s\n", f.ToPort)
|
fmt.Fprintf(w, "To port:\t%s\n", f.ToPort)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "To (IPv6):\t%s\nFrom:\t%s\nHairpin:\t%s %s\n", orDash(f.To6), list(f.Sources), yesNo(f.Hairpin), list(f.HairpinSources))
|
hairpin := yesNo(f.Hairpin)
|
||||||
|
if f.Hairpin && len(f.HairpinSources) > 0 {
|
||||||
|
hairpin += ", from " + list(f.HairpinSources)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "To (IPv6):\t%s\nFrom:\t%s\nHairpin:\t%s\n", orDash(f.To6), list(f.Sources), hairpin)
|
||||||
|
if f.Comment != "" {
|
||||||
|
fmt.Fprintf(w, "Comment:\t%s\n", f.Comment)
|
||||||
|
}
|
||||||
|
cs := counters()
|
||||||
|
fmt.Fprintf(w, "Hits:\t%s\n", hits(cs, fmt.Sprintf("f%d", f.ID), fmt.Sprintf("f%d-6", f.ID)))
|
||||||
}))
|
}))
|
||||||
var pf model.PortForward
|
var pf model.PortForward
|
||||||
var to string
|
var to string
|
||||||
|
|||||||
@@ -84,7 +84,11 @@ func ParseAddress(s string) (Address, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Address{}, fmt.Errorf("%q is not an address or prefix", s)
|
return Address{}, fmt.Errorf("%q is not an address or prefix", s)
|
||||||
}
|
}
|
||||||
p = netip.PrefixFrom(p.Addr().Unmap(), p.Bits())
|
if p.Addr().Is4In6() {
|
||||||
|
// Unmapping would leave an IPv4 address with IPv6 bits
|
||||||
|
// (::ffff:0:0/96 as 0.0.0.0/96).
|
||||||
|
return Address{}, fmt.Errorf("%q is an IPv4-mapped prefix, which can't be used: write IPv4 prefixes as IPv4 (10.0.0.0/8)", s)
|
||||||
|
}
|
||||||
if p.Masked() != p {
|
if p.Masked() != p {
|
||||||
return Address{}, fmt.Errorf("%q has host bits set; the prefix is %s", s, p.Masked())
|
return Address{}, fmt.Errorf("%q has host bits set; the prefix is %s", s, p.Masked())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseAddress(t *testing.T) {
|
||||||
|
for _, c := range []struct{ in, want, err string }{
|
||||||
|
{in: "10.0.0.0/8", want: "10.0.0.0/8"},
|
||||||
|
{in: "2001:db8::/32", want: "2001:db8::/32"},
|
||||||
|
{in: "::ffff:10.0.0.1", want: "10.0.0.1"},
|
||||||
|
{in: "10.0.0.1/8", err: "host bits"},
|
||||||
|
{in: "::ffff:0:0/96", err: "IPv4-mapped"},
|
||||||
|
{in: "::ffff:10.0.0.0/104", err: "IPv4-mapped"},
|
||||||
|
} {
|
||||||
|
a, err := ParseAddress(c.in)
|
||||||
|
if c.err != "" {
|
||||||
|
if err == nil || !strings.Contains(err.Error(), c.err) {
|
||||||
|
t.Errorf("%s: error %v, want one saying %q", c.in, err, c.err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil || a.String() != c.want {
|
||||||
|
t.Errorf("%s: %q, %v; want %q", c.in, a.String(), err, c.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user