diff --git a/cmd/keyctl/main.go b/cmd/keyctl/main.go index 97b5ee5..022a56a 100644 --- a/cmd/keyctl/main.go +++ b/cmd/keyctl/main.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "os/signal" + "path/filepath" "syscall" "time" @@ -23,6 +24,7 @@ var ( version string listen string + socket string path string log logr.Logger @@ -58,6 +60,7 @@ func main() { fs := flag.NewFlagSet("", flag.ExitOnError) klog.InitFlags(fs) fs.StringVar(&listen, "listen", ":7070", "listen ip:port") + fs.StringVar(&socket, "socket", "keyctl.sock", "listen unix domain socket") fs.StringVar(&path, "path", "/var/keyctl", "db storage dir") fs.Parse(os.Args[2:]) default: @@ -66,7 +69,7 @@ func main() { log = klogr.New().WithName("main") log.Info("starting keyctl", "version", version) - srv, err := api.NewServer(klogr.New().WithName("srv"), listen) + srv, err := api.NewServer(klogr.New().WithName("srv"), listen, filepath.Join(path, socket)) if err != nil { klog.Fatalf("init failed: %s", err) } diff --git a/pkg/api/client/client.go b/pkg/api/client/client.go index c59bb00..2f5168c 100644 --- a/pkg/api/client/client.go +++ b/pkg/api/client/client.go @@ -11,6 +11,7 @@ import ( "net" "net/http" "net/http/httputil" + "net/url" "os" "strings" "time" @@ -19,6 +20,8 @@ import ( type Client struct { endpoint string httpClient *http.Client + dialer *net.Dialer + dialerFunc func(ctx context.Context, network, addr string) (net.Conn, error) debugWriter io.Writer //insecure bool } @@ -31,6 +34,22 @@ type ClientOption func(*Client) func WithEndpoint(endpoint string) ClientOption { return func(client *Client) { + u, err := url.Parse(endpoint) + if err != nil { + return + } + client.dialer = &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + } + if u.Scheme == "unix" { + client.dialerFunc = func(ctx context.Context, network, addr string) (net.Conn, error) { + return client.dialer.DialContext(ctx, "unix", u.Path) + } + client.endpoint = "http://unix" + return + } + client.dialerFunc = client.dialer.DialContext client.endpoint = strings.TrimRight(endpoint, "/") } } @@ -104,10 +123,7 @@ func NewClient(options ...ClientOption) *Client { return http.ErrUseLastResponse }, Transport: &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, + DialContext: client.dialerFunc, //ForceAttemptHTTP2: true, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, diff --git a/pkg/api/server.go b/pkg/api/server.go index 6f80b85..0d36150 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -6,6 +6,7 @@ import ( "context" "net" "net/http" + "os" "time" "git.giftfish.de/ston1th/keyctl/pkg/api/types" @@ -25,6 +26,7 @@ type Server struct { Data *types.ContextData listen net.Listener + socket net.Listener } type notFoundHandler struct { @@ -36,7 +38,7 @@ func (nf *notFoundHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // NewHTTPServer returns a new HTTPServer -func NewServer(log logr.Logger, listen string) (*Server, error) { +func NewServer(log logr.Logger, listen, socket string) (*Server, error) { s := &Server{ mux: mux.NewRouter(), log: log, @@ -48,6 +50,13 @@ func NewServer(log logr.Logger, listen string) (*Server, error) { } s.listen = l + sock, err := unixListener(socket) + net.Listen("unix", socket) + if err != nil { + return nil, err + } + s.socket = sock + s.mux.NotFoundHandler = ¬FoundHandler{s} for _, v := range serverv1.Routes { s.mux.HandleFunc(v.Path, s.contextWrapper(v.Handler)).Methods(v.Methods...) @@ -55,6 +64,15 @@ func NewServer(log logr.Logger, listen string) (*Server, error) { return s, nil } +func unixListener(socket string) (sock net.Listener, err error) { + sock, err = net.Listen("unix", socket) + if err != nil { + return + } + err = os.Chmod(socket, 0660) + return +} + func (s *Server) Start(db *db.DB) { s.srv = &http.Server{ Handler: s.mux, @@ -68,6 +86,12 @@ func (s *Server) Start(db *db.DB) { s.log.Error(err, "") } }() + go func() { + err := s.srv.Serve(s.socket) + if err != nil && err != http.ErrServerClosed { + s.log.Error(err, "") + } + }() return } diff --git a/pkg/api/types/context.go b/pkg/api/types/context.go index aa5d254..d263227 100644 --- a/pkg/api/types/context.go +++ b/pkg/api/types/context.go @@ -40,6 +40,8 @@ type Context struct { Data *ContextData Log logr.Logger + + ip string } // Method returns the request method @@ -69,7 +71,15 @@ func (c *Context) Form(name string) string { } func (c *Context) ClientIP() (host string) { - host, _, _ = net.SplitHostPort(c.Request.RemoteAddr) + host = c.Request.RemoteAddr + if host == "@" { + return + } + if c.ip != "" { + return c.ip + } + host, _, _ = net.SplitHostPort(host) + c.ip = host return } diff --git a/pkg/api/v1/server/handler.go b/pkg/api/v1/server/handler.go index e10d438..550cba2 100644 --- a/pkg/api/v1/server/handler.go +++ b/pkg/api/v1/server/handler.go @@ -5,7 +5,6 @@ package server import ( "encoding/json" "net/http" - "net/netip" "git.giftfish.de/ston1th/keyctl/pkg/api/types" "git.giftfish.de/ston1th/keyctl/pkg/api/v1/schema" @@ -14,16 +13,21 @@ import ( func local(h types.CtxHandler) types.CtxHandler { return func(ctx *types.Context) { - addr, err := netip.ParseAddr(ctx.ClientIP()) - if err != nil { - ctx.Err(types.ErrForbidden) + ip := ctx.ClientIP() + if ip == "@" { + h(ctx) return } - if !addr.IsLoopback() { - ctx.Err(types.ErrForbidden) - return - } - h(ctx) + //addr, err := netip.ParseAddr(ip) + //if err != nil { + // ctx.Err(types.ErrForbidden) + // return + //} + //if addr.IsLoopback() { + // h(ctx) + // return + //} + ctx.Err(types.ErrForbidden) } }