Merge prototype/reverse-proxy with proxy clustering support

Combines token-based authentication from upstream with proxy clustering:
- Session keys for JWT signing (SessionPrivateKey/SessionPublicKey)
- One-time token store for proxy authentication
- Cluster-targeted updates via SendReverseProxyUpdateToCluster
- ProxyCluster field derived from domain
- OIDC validation config support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
mlsmaycon
2026-02-05 14:08:07 +01:00
co-authored by Claude Opus 4.5
73 changed files with 5239 additions and 1253 deletions
File diff suppressed because it is too large Load Diff
+36 -15
View File
@@ -16,6 +16,10 @@ service ProxyService {
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse);
rpc SendStatusUpdate(SendStatusUpdateRequest) returns (SendStatusUpdateResponse);
rpc CreateProxyPeer(CreateProxyPeerRequest) returns (CreateProxyPeerResponse);
rpc GetOIDCURL(GetOIDCURLRequest) returns (GetOIDCURLResponse);
}
// GetMappingUpdateRequest is sent to initialise a mapping stream.
@@ -45,14 +49,11 @@ message PathMapping {
}
message Authentication {
bool password = 1;
bool pin = 2;
optional OIDC oidc = 3;
bool link = 4;
}
message OIDC {
repeated string distribution_groups = 1;
string session_key = 1;
int64 max_session_age_seconds = 2;
bool password = 3;
bool pin = 4;
bool oidc = 5;
}
message ProxyMapping {
@@ -61,7 +62,7 @@ message ProxyMapping {
string account_id = 3;
string domain = 4;
repeated PathMapping path = 5;
string setup_key = 6;
string auth_token = 6;
Authentication auth = 7;
}
@@ -95,7 +96,6 @@ message AuthenticateRequest {
oneof request {
PasswordRequest password = 3;
PinRequest pin = 4;
LinkRequest link = 5;
}
}
@@ -107,13 +107,9 @@ message PinRequest {
string pin = 1;
}
message LinkRequest {
string email = 1;
string redirect = 2;
}
message AuthenticateResponse {
bool success = 1;
string session_token = 2;
}
enum ProxyStatus {
@@ -136,3 +132,28 @@ message SendStatusUpdateRequest {
// SendStatusUpdateResponse is intentionally empty to allow for future expansion
message SendStatusUpdateResponse {}
// CreateProxyPeerRequest is sent by the proxy to create a peer connection
// The token is a one-time authentication token sent via ProxyMapping
message CreateProxyPeerRequest {
string reverse_proxy_id = 1;
string account_id = 2;
string token = 3;
string wireguard_public_key = 4;
}
// CreateProxyPeerResponse contains the result of peer creation
message CreateProxyPeerResponse {
bool success = 1;
optional string error_message = 2;
}
message GetOIDCURLRequest {
string id = 1;
string account_id = 2;
string redirect_url = 3;
}
message GetOIDCURLResponse {
string url = 1;
}
@@ -22,6 +22,8 @@ type ProxyServiceClient interface {
SendAccessLog(ctx context.Context, in *SendAccessLogRequest, opts ...grpc.CallOption) (*SendAccessLogResponse, error)
Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error)
CreateProxyPeer(ctx context.Context, in *CreateProxyPeerRequest, opts ...grpc.CallOption) (*CreateProxyPeerResponse, error)
GetOIDCURL(ctx context.Context, in *GetOIDCURLRequest, opts ...grpc.CallOption) (*GetOIDCURLResponse, error)
}
type proxyServiceClient struct {
@@ -91,6 +93,24 @@ func (c *proxyServiceClient) SendStatusUpdate(ctx context.Context, in *SendStatu
return out, nil
}
func (c *proxyServiceClient) CreateProxyPeer(ctx context.Context, in *CreateProxyPeerRequest, opts ...grpc.CallOption) (*CreateProxyPeerResponse, error) {
out := new(CreateProxyPeerResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/CreateProxyPeer", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) GetOIDCURL(ctx context.Context, in *GetOIDCURLRequest, opts ...grpc.CallOption) (*GetOIDCURLResponse, error) {
out := new(GetOIDCURLResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/GetOIDCURL", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ProxyServiceServer is the server API for ProxyService service.
// All implementations must embed UnimplementedProxyServiceServer
// for forward compatibility
@@ -99,6 +119,8 @@ type ProxyServiceServer interface {
SendAccessLog(context.Context, *SendAccessLogRequest) (*SendAccessLogResponse, error)
Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error)
CreateProxyPeer(context.Context, *CreateProxyPeerRequest) (*CreateProxyPeerResponse, error)
GetOIDCURL(context.Context, *GetOIDCURLRequest) (*GetOIDCURLResponse, error)
mustEmbedUnimplementedProxyServiceServer()
}
@@ -118,6 +140,12 @@ func (UnimplementedProxyServiceServer) Authenticate(context.Context, *Authentica
func (UnimplementedProxyServiceServer) SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SendStatusUpdate not implemented")
}
func (UnimplementedProxyServiceServer) CreateProxyPeer(context.Context, *CreateProxyPeerRequest) (*CreateProxyPeerResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateProxyPeer not implemented")
}
func (UnimplementedProxyServiceServer) GetOIDCURL(context.Context, *GetOIDCURLRequest) (*GetOIDCURLResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOIDCURL not implemented")
}
func (UnimplementedProxyServiceServer) mustEmbedUnimplementedProxyServiceServer() {}
// UnsafeProxyServiceServer may be embedded to opt out of forward compatibility for this service.
@@ -206,6 +234,42 @@ func _ProxyService_SendStatusUpdate_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler)
}
func _ProxyService_CreateProxyPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateProxyPeerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).CreateProxyPeer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/CreateProxyPeer",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).CreateProxyPeer(ctx, req.(*CreateProxyPeerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_GetOIDCURL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetOIDCURLRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).GetOIDCURL(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/GetOIDCURL",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).GetOIDCURL(ctx, req.(*GetOIDCURLRequest))
}
return interceptor(ctx, in, info, handler)
}
// ProxyService_ServiceDesc is the grpc.ServiceDesc for ProxyService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -225,6 +289,14 @@ var ProxyService_ServiceDesc = grpc.ServiceDesc{
MethodName: "SendStatusUpdate",
Handler: _ProxyService_SendStatusUpdate_Handler,
},
{
MethodName: "CreateProxyPeer",
Handler: _ProxyService_CreateProxyPeer_Handler,
},
{
MethodName: "GetOIDCURL",
Handler: _ProxyService_GetOIDCURL_Handler,
},
},
Streams: []grpc.StreamDesc{
{