Rename the project to ihasvpn
WGX shares its name with several other WireGuard tools, so the project becomes ihasvpn, alongside ihasmail. - Module github.com/Coffey-Labs/ihasvpn, command cmd/ihasvpn, image ghcr.io/coffey-labs/ihasvpn. - Environment variables move from WGX_* to IHASVPN_*. The default database is ihasvpn.db, the nftables table is `ihasvpn`, metrics are ihasvpn_*, and the session cookie and theme key are renamed, so existing sessions end. - The mark is the ihasmail cat peeking over the edge of a shield, drawn as a vector. docs/brand/generate.py builds the mark, mono mark, wordmarks, social card, favicons and app icons from that one drawing. - The console takes ihasmail's palette: the ihasmail.org teal-navy for dark, its contrast-checked light tiers with the site's light accent, received traffic in the cat's orange and sent in teal. The wordmark weight and font stack follow ihasmail.org. - Detail values wrap at spaces before breaking inside an address, so an IPv6 tunnel address no longer splits mid-number. - The README history note about the earlier WGX installer is gone with the name it explained. Screenshots retaken.
This commit is contained in:
@@ -85,7 +85,7 @@ func VerifyPassword(hash, pw string) bool {
|
||||
|
||||
// dummyHash is verified against when the user does not exist, so a login
|
||||
// for an unknown name takes as long as one for a known name.
|
||||
var dummyHash, _ = HashPassword("wgx-timing-equaliser-password")
|
||||
var dummyHash, _ = HashPassword("ihasvpn-timing-equaliser-password")
|
||||
|
||||
// EqualiseTiming burns the cost of one hash verification.
|
||||
func EqualiseTiming() { VerifyPassword(dummyHash, "not-the-password") }
|
||||
|
||||
+35
-35
@@ -104,52 +104,52 @@ func envDuration(key string, def time.Duration) (time.Duration, error) {
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// FromEnv builds the configuration from WGX_* variables.
|
||||
// FromEnv builds the configuration from IHASVPN_* variables.
|
||||
func FromEnv() (*Config, error) {
|
||||
var errs []error
|
||||
c := &Config{}
|
||||
c.DataDir = env("WGX_DATA_DIR", "/data")
|
||||
c.DBPath = env("WGX_DB", c.DataDir+"/wgx.db")
|
||||
c.Backend = strings.ToLower(env("WGX_BACKEND", "auto"))
|
||||
c.DataDir = env("IHASVPN_DATA_DIR", "/data")
|
||||
c.DBPath = env("IHASVPN_DB", c.DataDir+"/ihasvpn.db")
|
||||
c.Backend = strings.ToLower(env("IHASVPN_BACKEND", "auto"))
|
||||
switch c.Backend {
|
||||
case "auto", "kernel", "userspace", "mock":
|
||||
default:
|
||||
errs = append(errs, fmt.Errorf("WGX_BACKEND: %q is not auto, kernel, userspace or mock", c.Backend))
|
||||
errs = append(errs, fmt.Errorf("IHASVPN_BACKEND: %q is not auto, kernel, userspace or mock", c.Backend))
|
||||
}
|
||||
c.Iface = env("WGX_INTERFACE", "wg0")
|
||||
c.Iface = env("IHASVPN_INTERFACE", "wg0")
|
||||
if len(c.Iface) == 0 || len(c.Iface) > 15 || strings.ContainsAny(c.Iface, " /\t\n") {
|
||||
errs = append(errs, errors.New("WGX_INTERFACE: must be 1-15 characters with no spaces or slashes"))
|
||||
errs = append(errs, errors.New("IHASVPN_INTERFACE: must be 1-15 characters with no spaces or slashes"))
|
||||
}
|
||||
var err error
|
||||
if c.ListenPort, err = envInt("WGX_PORT", 51820); err != nil {
|
||||
if c.ListenPort, err = envInt("IHASVPN_PORT", 51820); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else if c.ListenPort < 1 || c.ListenPort > 65535 {
|
||||
errs = append(errs, errors.New("WGX_PORT: must be 1-65535"))
|
||||
errs = append(errs, errors.New("IHASVPN_PORT: must be 1-65535"))
|
||||
}
|
||||
if c.Subnet4, err = netip.ParsePrefix(env("WGX_SUBNET", "10.8.0.0/24")); err != nil || !c.Subnet4.Addr().Is4() {
|
||||
errs = append(errs, errors.New("WGX_SUBNET: must be an IPv4 CIDR such as 10.8.0.0/24"))
|
||||
if c.Subnet4, err = netip.ParsePrefix(env("IHASVPN_SUBNET", "10.8.0.0/24")); err != nil || !c.Subnet4.Addr().Is4() {
|
||||
errs = append(errs, errors.New("IHASVPN_SUBNET: must be an IPv4 CIDR such as 10.8.0.0/24"))
|
||||
} else if c.Subnet4.Bits() > 30 {
|
||||
errs = append(errs, errors.New("WGX_SUBNET: needs room for at least two hosts (/30 or larger)"))
|
||||
errs = append(errs, errors.New("IHASVPN_SUBNET: needs room for at least two hosts (/30 or larger)"))
|
||||
}
|
||||
if v := env("WGX_SUBNET6", ""); v != "" {
|
||||
if v := env("IHASVPN_SUBNET6", ""); v != "" {
|
||||
if c.Subnet6, err = netip.ParsePrefix(v); err != nil || !c.Subnet6.Addr().Is6() {
|
||||
errs = append(errs, errors.New("WGX_SUBNET6: must be an IPv6 CIDR such as fd42:42:42::/64"))
|
||||
errs = append(errs, errors.New("IHASVPN_SUBNET6: must be an IPv6 CIDR such as fd42:42:42::/64"))
|
||||
}
|
||||
}
|
||||
c.Egress = env("WGX_EGRESS_INTERFACE", "")
|
||||
c.HTTP = env("WGX_HTTP_LISTEN", ":51821")
|
||||
c.TLSCert = env("WGX_TLS_CERT", "")
|
||||
c.TLSKey = env("WGX_TLS_KEY", "")
|
||||
c.Egress = env("IHASVPN_EGRESS_INTERFACE", "")
|
||||
c.HTTP = env("IHASVPN_HTTP_LISTEN", ":51821")
|
||||
c.TLSCert = env("IHASVPN_TLS_CERT", "")
|
||||
c.TLSKey = env("IHASVPN_TLS_KEY", "")
|
||||
if (c.TLSCert == "") != (c.TLSKey == "") {
|
||||
errs = append(errs, errors.New("WGX_TLS_CERT and WGX_TLS_KEY must be set together"))
|
||||
errs = append(errs, errors.New("IHASVPN_TLS_CERT and IHASVPN_TLS_KEY must be set together"))
|
||||
}
|
||||
if c.TLSSelfSigned, err = envBool("WGX_TLS_SELF_SIGNED", false); err != nil {
|
||||
if c.TLSSelfSigned, err = envBool("IHASVPN_TLS_SELF_SIGNED", false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if c.SecureCookies, err = envBool("WGX_SECURE_COOKIES", false); err != nil {
|
||||
if c.SecureCookies, err = envBool("IHASVPN_SECURE_COOKIES", false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
for _, p := range strings.Split(env("WGX_TRUSTED_PROXIES", ""), ",") {
|
||||
for _, p := range strings.Split(env("IHASVPN_TRUSTED_PROXIES", ""), ",") {
|
||||
p = strings.TrimSpace(p)
|
||||
if p == "" {
|
||||
continue
|
||||
@@ -159,37 +159,37 @@ func FromEnv() (*Config, error) {
|
||||
if a, err2 := netip.ParseAddr(p); err2 == nil {
|
||||
pfx = netip.PrefixFrom(a, a.BitLen())
|
||||
} else {
|
||||
errs = append(errs, fmt.Errorf("WGX_TRUSTED_PROXIES: %q is not an address or CIDR", p))
|
||||
errs = append(errs, fmt.Errorf("IHASVPN_TRUSTED_PROXIES: %q is not an address or CIDR", p))
|
||||
continue
|
||||
}
|
||||
}
|
||||
c.TrustedProxies = append(c.TrustedProxies, pfx)
|
||||
}
|
||||
c.MetricsToken = env("WGX_METRICS_TOKEN", "")
|
||||
if c.SessionIdle, err = envDuration("WGX_SESSION_IDLE", 12*time.Hour); err != nil {
|
||||
c.MetricsToken = env("IHASVPN_METRICS_TOKEN", "")
|
||||
if c.SessionIdle, err = envDuration("IHASVPN_SESSION_IDLE", 12*time.Hour); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if c.SessionMax, err = envDuration("WGX_SESSION_MAX", 7*24*time.Hour); err != nil {
|
||||
if c.SessionMax, err = envDuration("IHASVPN_SESSION_MAX", 7*24*time.Hour); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if c.TrafficRetention, err = envDuration("WGX_TRAFFIC_RETENTION", 90*24*time.Hour); err != nil {
|
||||
if c.TrafficRetention, err = envDuration("IHASVPN_TRAFFIC_RETENTION", 90*24*time.Hour); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if c.PollInterval, err = envDuration("WGX_POLL_INTERVAL", 2*time.Second); err != nil {
|
||||
if c.PollInterval, err = envDuration("IHASVPN_POLL_INTERVAL", 2*time.Second); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else if c.PollInterval < 500*time.Millisecond {
|
||||
errs = append(errs, errors.New("WGX_POLL_INTERVAL: must be at least 500ms"))
|
||||
errs = append(errs, errors.New("IHASVPN_POLL_INTERVAL: must be at least 500ms"))
|
||||
}
|
||||
c.LogLevel = strings.ToLower(env("WGX_LOG_LEVEL", "info"))
|
||||
if c.LogJSON, err = envBool("WGX_LOG_JSON", false); err != nil {
|
||||
c.LogLevel = strings.ToLower(env("IHASVPN_LOG_LEVEL", "info"))
|
||||
if c.LogJSON, err = envBool("IHASVPN_LOG_JSON", false); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
c.InitialEndpoint = env("WGX_ENDPOINT", "")
|
||||
c.InitialDNS = env("WGX_DNS", "1.1.1.1, 1.0.0.1")
|
||||
if c.ManageFirewall, err = envBool("WGX_MANAGE_FIREWALL", true); err != nil {
|
||||
c.InitialEndpoint = env("IHASVPN_ENDPOINT", "")
|
||||
c.InitialDNS = env("IHASVPN_DNS", "1.1.1.1, 1.0.0.1")
|
||||
if c.ManageFirewall, err = envBool("IHASVPN_MANAGE_FIREWALL", true); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if c.ManageSysctl, err = envBool("WGX_MANAGE_SYSCTL", true); err != nil {
|
||||
if c.ManageSysctl, err = envBool("IHASVPN_MANAGE_SYSCTL", true); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
)
|
||||
|
||||
// Live is what the data plane currently says about one peer, merged with
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/config"
|
||||
"github.com/Coffey-Labs/WGX/internal/netcfg"
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/WGX/internal/wg"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/config"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/netcfg"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/wg"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/config"
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/WGX/internal/wg"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/config"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/wg"
|
||||
)
|
||||
|
||||
func testConfig() *config.Config {
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
|
||||
"github.com/skip2/go-qrcode"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/auth"
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/WGX/internal/wg"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/auth"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/wg"
|
||||
)
|
||||
|
||||
// PeerInput is what the API accepts when creating or editing a peer.
|
||||
@@ -170,7 +170,7 @@ func (e *Engine) CreatePeer(ctx context.Context, in PeerInput) (*store.Peer, err
|
||||
}
|
||||
p.IPv6 = a6.String()
|
||||
} else if in.IPv6 != "" {
|
||||
return nil, invalid("IPv6 is not enabled on this server (set WGX_SUBNET6)")
|
||||
return nil, invalid("IPv6 is not enabled on this server (set IHASVPN_SUBNET6)")
|
||||
}
|
||||
if err := applyEditable(p, in, settings); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
)
|
||||
|
||||
// Settings are the administrator-editable server options. They persist in the
|
||||
|
||||
@@ -3,7 +3,7 @@ package engine
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/netcfg"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/netcfg"
|
||||
)
|
||||
|
||||
// SysctlStatus is one sysctl as reported to the UI.
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Rules describes the firewall WGX wants.
|
||||
// Rules describes the firewall ihasvpn wants.
|
||||
type Rules struct {
|
||||
// Iface is the WireGuard interface name, e.g. wg0.
|
||||
Iface string
|
||||
@@ -31,7 +31,7 @@ type Rules struct {
|
||||
// "the VPN connects but websites hang".
|
||||
ClampMSS bool
|
||||
// Table names the nftables table, so a host with its own rules never
|
||||
// collides with ours. Defaults to "wgx".
|
||||
// collides with ours. Defaults to "ihasvpn".
|
||||
Table string
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ type Rules struct {
|
||||
func Ruleset(r Rules) string {
|
||||
table := r.Table
|
||||
if table == "" {
|
||||
table = "wgx"
|
||||
table = "ihasvpn"
|
||||
}
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "table inet %s\n", table)
|
||||
@@ -88,10 +88,10 @@ func Apply(ctx context.Context, r Rules) error {
|
||||
return runNFT(ctx, Ruleset(r))
|
||||
}
|
||||
|
||||
// Remove deletes the WGX table, ignoring the case where it is already gone.
|
||||
// Remove deletes the ihasvpn table, ignoring the case where it is already gone.
|
||||
func Remove(ctx context.Context, table string) error {
|
||||
if table == "" {
|
||||
table = "wgx"
|
||||
table = "ihasvpn"
|
||||
}
|
||||
script := fmt.Sprintf("table inet %s\ndelete table inet %s\n", table, table)
|
||||
return runNFT(ctx, script)
|
||||
|
||||
@@ -17,7 +17,7 @@ func TestRuleset(t *testing.T) {
|
||||
}
|
||||
out := Ruleset(r)
|
||||
for _, want := range []string{
|
||||
"table inet wgx {",
|
||||
"table inet ihasvpn {",
|
||||
"udp dport 51820 accept",
|
||||
`iifname "wg0" oifname "wg0" drop`,
|
||||
`tcp option maxseg size set rt mtu`,
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Sysctl is one kernel parameter and the value WGX wants for it.
|
||||
// Sysctl is one kernel parameter and the value ihasvpn wants for it.
|
||||
type Sysctl struct {
|
||||
Key string
|
||||
Value string
|
||||
@@ -27,7 +27,7 @@ type Result struct {
|
||||
Err string
|
||||
}
|
||||
|
||||
// Wanted returns the sysctls WGX applies at startup, in order.
|
||||
// Wanted returns the sysctls ihasvpn applies at startup, in order.
|
||||
func Wanted(ipv6 bool) []Sysctl {
|
||||
s := []Sysctl{
|
||||
{Key: "net.ipv4.ip_forward", Value: "1", Required: true, Why: "peers cannot reach anything beyond the server without forwarding"},
|
||||
|
||||
+13
-13
@@ -8,8 +8,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/engine"
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/engine"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
)
|
||||
|
||||
type healthBody struct {
|
||||
@@ -192,7 +192,7 @@ func safeFilename(name string) string {
|
||||
}
|
||||
out := b.String()
|
||||
if out == "" {
|
||||
out = "wgx"
|
||||
out = "ihasvpn"
|
||||
}
|
||||
if len(out) > 15 {
|
||||
// wg-quick derives the interface name from the file name and caps it
|
||||
@@ -374,28 +374,28 @@ func (s *Server) handleMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8")
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "# HELP wgx_peers Number of configured peers.\n# TYPE wgx_peers gauge\nwgx_peers %d\n", snap.Totals.Peers)
|
||||
fmt.Fprintf(&b, "# HELP wgx_peers_connected Peers with a recent handshake.\n# TYPE wgx_peers_connected gauge\nwgx_peers_connected %d\n", snap.Totals.Connected)
|
||||
fmt.Fprintf(&b, "# HELP wgx_receive_bytes_total Bytes received from peers.\n# TYPE wgx_receive_bytes_total counter\n")
|
||||
fmt.Fprintf(&b, "# HELP ihasvpn_peers Number of configured peers.\n# TYPE ihasvpn_peers gauge\nihasvpn_peers %d\n", snap.Totals.Peers)
|
||||
fmt.Fprintf(&b, "# HELP ihasvpn_peers_connected Peers with a recent handshake.\n# TYPE ihasvpn_peers_connected gauge\nihasvpn_peers_connected %d\n", snap.Totals.Connected)
|
||||
fmt.Fprintf(&b, "# HELP ihasvpn_receive_bytes_total Bytes received from peers.\n# TYPE ihasvpn_receive_bytes_total counter\n")
|
||||
for id, l := range snap.Peers {
|
||||
fmt.Fprintf(&b, "wgx_receive_bytes_total{peer=%q,name=%q} %d\n", id, names[id], l.Rx)
|
||||
fmt.Fprintf(&b, "ihasvpn_receive_bytes_total{peer=%q,name=%q} %d\n", id, names[id], l.Rx)
|
||||
}
|
||||
fmt.Fprintf(&b, "# HELP wgx_transmit_bytes_total Bytes sent to peers.\n# TYPE wgx_transmit_bytes_total counter\n")
|
||||
fmt.Fprintf(&b, "# HELP ihasvpn_transmit_bytes_total Bytes sent to peers.\n# TYPE ihasvpn_transmit_bytes_total counter\n")
|
||||
for id, l := range snap.Peers {
|
||||
fmt.Fprintf(&b, "wgx_transmit_bytes_total{peer=%q,name=%q} %d\n", id, names[id], l.Tx)
|
||||
fmt.Fprintf(&b, "ihasvpn_transmit_bytes_total{peer=%q,name=%q} %d\n", id, names[id], l.Tx)
|
||||
}
|
||||
fmt.Fprintf(&b, "# HELP wgx_peer_connected Whether the peer has a recent handshake.\n# TYPE wgx_peer_connected gauge\n")
|
||||
fmt.Fprintf(&b, "# HELP ihasvpn_peer_connected Whether the peer has a recent handshake.\n# TYPE ihasvpn_peer_connected gauge\n")
|
||||
for id, l := range snap.Peers {
|
||||
v := 0
|
||||
if l.Connected {
|
||||
v = 1
|
||||
}
|
||||
fmt.Fprintf(&b, "wgx_peer_connected{peer=%q,name=%q} %d\n", id, names[id], v)
|
||||
fmt.Fprintf(&b, "ihasvpn_peer_connected{peer=%q,name=%q} %d\n", id, names[id], v)
|
||||
}
|
||||
fmt.Fprintf(&b, "# HELP wgx_peer_last_handshake_seconds Unix time of the last handshake.\n# TYPE wgx_peer_last_handshake_seconds gauge\n")
|
||||
fmt.Fprintf(&b, "# HELP ihasvpn_peer_last_handshake_seconds Unix time of the last handshake.\n# TYPE ihasvpn_peer_last_handshake_seconds gauge\n")
|
||||
for id, l := range snap.Peers {
|
||||
if !l.LastHandshake.IsZero() {
|
||||
fmt.Fprintf(&b, "wgx_peer_last_handshake_seconds{peer=%q,name=%q} %d\n", id, names[id], l.LastHandshake.Unix())
|
||||
fmt.Fprintf(&b, "ihasvpn_peer_last_handshake_seconds{peer=%q,name=%q} %d\n", id, names[id], l.LastHandshake.Unix())
|
||||
}
|
||||
}
|
||||
_, _ = w.Write([]byte(b.String()))
|
||||
|
||||
@@ -10,11 +10,11 @@ import (
|
||||
|
||||
"github.com/skip2/go-qrcode"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/auth"
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/auth"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
)
|
||||
|
||||
const cookieName = "wgx_session"
|
||||
const cookieName = "ihasvpn_session"
|
||||
|
||||
type ctxKey int
|
||||
|
||||
@@ -450,7 +450,7 @@ func (s *Server) handleTOTPSetup(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, totpSetupResponse{Secret: secret, URI: auth.TOTPURI("WGX", u.Username, secret)})
|
||||
writeJSON(w, http.StatusOK, totpSetupResponse{Secret: secret, URI: auth.TOTPURI("ihasvpn", u.Username, secret)})
|
||||
}
|
||||
|
||||
// handleTOTPQR renders the pending secret's otpauth URI as a QR code. Only a
|
||||
@@ -462,7 +462,7 @@ func (s *Server) handleTOTPQR(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusNotFound, "no two-factor setup in progress")
|
||||
return
|
||||
}
|
||||
png, err := qrcode.Encode(auth.TOTPURI("WGX", u.Username, u.TOTPSecret), qrcode.Medium, 256)
|
||||
png, err := qrcode.Encode(auth.TOTPURI("ihasvpn", u.Username, u.TOTPSecret), qrcode.Medium, 256)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/auth"
|
||||
"github.com/Coffey-Labs/WGX/internal/config"
|
||||
"github.com/Coffey-Labs/WGX/internal/engine"
|
||||
"github.com/Coffey-Labs/WGX/internal/server/static"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/auth"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/config"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/engine"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/server/static"
|
||||
)
|
||||
|
||||
// Server serves the API and UI.
|
||||
|
||||
@@ -14,11 +14,11 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Coffey-Labs/WGX/internal/auth"
|
||||
"github.com/Coffey-Labs/WGX/internal/config"
|
||||
"github.com/Coffey-Labs/WGX/internal/engine"
|
||||
"github.com/Coffey-Labs/WGX/internal/store"
|
||||
"github.com/Coffey-Labs/WGX/internal/wg"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/auth"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/config"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/engine"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/store"
|
||||
"github.com/Coffey-Labs/ihasvpn/internal/wg"
|
||||
)
|
||||
|
||||
type client struct {
|
||||
@@ -178,7 +178,7 @@ func TestSetupLoginAndPeers(t *testing.T) {
|
||||
req.Header.Set("Authorization", "Bearer metrics-secret")
|
||||
r, _ := anon.Do(req)
|
||||
b, _ := io.ReadAll(r.Body)
|
||||
if r.StatusCode != 200 || !strings.Contains(string(b), "wgx_peers ") {
|
||||
if r.StatusCode != 200 || !strings.Contains(string(b), "ihasvpn_peers ") {
|
||||
t.Fatalf("token metrics: %d %s", r.StatusCode, b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (s *Server) loadCertificate() (tls.Certificate, error) {
|
||||
host := s.eng.Settings().EndpointHost
|
||||
tmpl := &x509.Certificate{
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{CommonName: "WGX", Organization: []string{"WGX"}},
|
||||
Subject: pkix.Name{CommonName: "ihasvpn", Organization: []string{"ihasvpn"}},
|
||||
NotBefore: time.Now().Add(-time.Hour),
|
||||
NotAfter: time.Now().Add(3 * 365 * 24 * time.Hour),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Package store is the SQLite persistence layer. Everything WGX remembers --
|
||||
// Package store is the SQLite persistence layer. Everything ihasvpn remembers --
|
||||
// peers and their keys, admin users, sessions, traffic history and the audit
|
||||
// log -- lives in one file under the data directory.
|
||||
package store
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Package wg abstracts the WireGuard data plane behind a small interface so the
|
||||
// rest of WGX does not care whether peers live in the kernel module, in a
|
||||
// rest of ihasvpn does not care whether peers live in the kernel module, in a
|
||||
// userspace wireguard-go process, or in an in-memory mock used by tests and
|
||||
// UI development.
|
||||
package wg
|
||||
@@ -25,7 +25,7 @@ type PeerState struct {
|
||||
PersistentKeepalive time.Duration
|
||||
}
|
||||
|
||||
// PeerConfig is what WGX wants a peer to look like on the interface.
|
||||
// PeerConfig is what ihasvpn wants a peer to look like on the interface.
|
||||
type PeerConfig struct {
|
||||
PublicKey Key
|
||||
PresharedKey *Key
|
||||
@@ -38,7 +38,7 @@ type DeviceConfig struct {
|
||||
PrivateKey Key
|
||||
ListenPort int
|
||||
// FirewallMark is applied to every packet the interface sends; zero means
|
||||
// none. Left at zero by WGX, but exposed for completeness.
|
||||
// none. Left at zero by ihasvpn, but exposed for completeness.
|
||||
FirewallMark int
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ type DeviceState struct {
|
||||
Peers []PeerState
|
||||
}
|
||||
|
||||
// Backend is the data plane WGX drives.
|
||||
// Backend is the data plane ihasvpn drives.
|
||||
type Backend interface {
|
||||
// Kind names the implementation: "kernel", "userspace" or "mock".
|
||||
Kind() string
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
// linuxBackend drives a real WireGuard interface. In kernel mode the link is a
|
||||
// native `wireguard` netlink link and every packet is handled by the module;
|
||||
// in userspace mode a wireguard-go process owns a TUN device with the same
|
||||
// name and WGX talks to it over its UAPI socket. Both are configured through
|
||||
// name and ihasvpn talks to it over its UAPI socket. Both are configured through
|
||||
// wgctrl, which picks the transport on its own.
|
||||
type linuxBackend struct {
|
||||
name string
|
||||
@@ -38,7 +38,7 @@ type linuxBackend struct {
|
||||
// trusting /sys/module, because a module that is loadable but not yet loaded
|
||||
// is only discovered by asking for it.
|
||||
func KernelAvailable() bool {
|
||||
const probe = "wgxprobe0"
|
||||
const probe = "ihasvpnprobe0"
|
||||
link := &netlink.Wireguard{LinkAttrs: netlink.LinkAttrs{Name: probe}}
|
||||
if err := netlink.LinkAdd(link); err != nil {
|
||||
return false
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
// Mock is an in-memory data plane. It needs no privileges, so it is what the
|
||||
// tests use and what `WGX_BACKEND=mock` gives a developer working on the UI.
|
||||
// tests use and what `IHASVPN_BACKEND=mock` gives a developer working on the UI.
|
||||
// With Simulate on, peers randomly handshake, move traffic and go quiet so
|
||||
// the dashboard has something to show.
|
||||
type Mock struct {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
var errLinuxOnly = errors.New("real WireGuard interfaces are only supported on Linux; use WGX_BACKEND=mock for development")
|
||||
var errLinuxOnly = errors.New("real WireGuard interfaces are only supported on Linux; use IHASVPN_BACKEND=mock for development")
|
||||
|
||||
// KernelAvailable is always false off Linux.
|
||||
func KernelAvailable() bool { return false }
|
||||
|
||||
Reference in New Issue
Block a user