Enhance Dockerfile to build and include a new HTTP API service (mtproxy_checkerd) alongside the existing CLI tool (mtproxy_checker). Update README and documentation to reflect the new service and its usage, including environment variables and Docker run instructions.
Publish mtproxy_checker Docker image / test (push) Successful in 11s
Publish mtproxy_checker Docker image / build-and-push (push) Successful in 56s

This commit is contained in:
Denozordec
2026-04-11 00:50:57 +07:00
parent 4905c06b9b
commit 5a66f0f2e8
8 changed files with 482 additions and 6 deletions
+60
View File
@@ -0,0 +1,60 @@
package allowlist
import (
"fmt"
"net/netip"
"strings"
)
// ParseCommaList parses MTPROXY_ALLOWED_IPS: comma-separated IPv4/IPv6 addresses or CIDR prefixes.
// Empty or whitespace-only input returns (nil, nil) meaning no restriction.
func ParseCommaList(s string) ([]netip.Prefix, error) {
s = strings.TrimSpace(s)
if s == "" {
return nil, nil
}
var out []netip.Prefix
for _, part := range strings.Split(s, ",") {
part = strings.TrimSpace(part)
if part == "" {
continue
}
pfx, err := parseEntry(part)
if err != nil {
return nil, fmt.Errorf("allowed_ips entry %q: %w", part, err)
}
out = append(out, pfx)
}
if len(out) == 0 {
return nil, nil
}
return out, nil
}
func parseEntry(s string) (netip.Prefix, error) {
if strings.Contains(s, "/") {
return netip.ParsePrefix(s)
}
addr, err := netip.ParseAddr(s)
if err != nil {
return netip.Prefix{}, err
}
bits := 32
if addr.Is6() {
bits = 128
}
return addr.Prefix(bits)
}
// Contains reports whether addr matches any prefix in list. Empty list means allow all.
func Contains(list []netip.Prefix, addr netip.Addr) bool {
if len(list) == 0 {
return true
}
for _, p := range list {
if p.Contains(addr) {
return true
}
}
return false
}
+32
View File
@@ -0,0 +1,32 @@
package allowlist
import (
"net/netip"
"testing"
)
func TestParseCommaList(t *testing.T) {
list, err := ParseCommaList(" ")
if err != nil || list != nil {
t.Fatalf("empty: list=%v err=%v", list, err)
}
list, err = ParseCommaList("192.168.1.1, 10.0.0.0/8")
if err != nil {
t.Fatal(err)
}
if len(list) != 2 {
t.Fatalf("want 2 prefixes, got %d", len(list))
}
a := netip.MustParseAddr("10.5.5.5")
if !Contains(list, a) {
t.Fatal("10.5.5.5 should match 10.0.0.0/8")
}
b := netip.MustParseAddr("192.168.1.1")
if !Contains(list, b) {
t.Fatal("192.168.1.1 should match host /32")
}
c := netip.MustParseAddr("8.8.8.8")
if Contains(list, c) {
t.Fatal("8.8.8.8 should not match")
}
}
+22
View File
@@ -0,0 +1,22 @@
package checkresult
import (
"context"
"errors"
"mtproxy_checker/internal/checker"
)
// Classify maps a checker error to CLI-style exit codes: 0 OK, 1 generic, 3 proxy closed, 4 timeout.
func Classify(err error) (exitCode int, message string) {
if err == nil {
return 0, ""
}
if errors.Is(err, checker.ErrProxyClosed) {
return 3, err.Error()
}
if errors.Is(err, context.DeadlineExceeded) {
return 4, "timeout"
}
return 1, err.Error()
}