Ingress for VIP

Signed-off-by: Irbe Krumina <irbe@tailscale.com>
irbekrm/splitkeys
Irbe Krumina 3 months ago
parent ab1eb428d9
commit 350d37286d

@ -155,6 +155,16 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
// magic443 is a fake hostname that we can use to tell containerboot to swap // magic443 is a fake hostname that we can use to tell containerboot to swap
// out with the real hostname once it's known. // out with the real hostname once it's known.
const magic443 = "${TS_CERT_DOMAIN}:443" const magic443 = "${TS_CERT_DOMAIN}:443"
tlsHostname := ""
if ing.Spec.TLS != nil && len(ing.Spec.TLS) > 0 && len(ing.Spec.TLS[0].Hosts) > 0 {
tlsHostname = ing.Spec.TLS[0].Hosts[0]
}
tlsHost := ipn.HostPort(fmt.Sprintf("%s:443", tlsHostname))
if tlsHostname == "" {
tlsHost = magic443
}
sc := &ipn.ServeConfig{ sc := &ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{ TCP: map[uint16]*ipn.TCPPortHandler{
443: { 443: {
@ -162,18 +172,18 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
}, },
}, },
Web: map[ipn.HostPort]*ipn.WebServerConfig{ Web: map[ipn.HostPort]*ipn.WebServerConfig{
magic443: { tlsHost: {
Handlers: map[string]*ipn.HTTPHandler{}, Handlers: map[string]*ipn.HTTPHandler{},
}, },
}, },
} }
if opt.Bool(ing.Annotations[AnnotationFunnel]).EqualBool(true) { if opt.Bool(ing.Annotations[AnnotationFunnel]).EqualBool(true) {
sc.AllowFunnel = map[ipn.HostPort]bool{ sc.AllowFunnel = map[ipn.HostPort]bool{
magic443: true, tlsHost: true,
} }
} }
web := sc.Web[magic443] web := sc.Web[tlsHost]
addIngressBackend := func(b *networkingv1.IngressBackend, path string) { addIngressBackend := func(b *networkingv1.IngressBackend, path string) {
if b == nil { if b == nil {
return return
@ -216,14 +226,10 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
} }
addIngressBackend(ing.Spec.DefaultBackend, "/") addIngressBackend(ing.Spec.DefaultBackend, "/")
var tlsHost string // hostname or FQDN or empty
if ing.Spec.TLS != nil && len(ing.Spec.TLS) > 0 && len(ing.Spec.TLS[0].Hosts) > 0 {
tlsHost = ing.Spec.TLS[0].Hosts[0]
}
for _, rule := range ing.Spec.Rules { for _, rule := range ing.Spec.Rules {
// Host is optional, but if it's present it must match the TLS host // Host is optional, but if it's present it must match the TLS host
// otherwise we ignore the rule. // otherwise we ignore the rule.
if rule.Host != "" && rule.Host != tlsHost { if rule.Host != "" && rule.Host != tlsHostname {
a.recorder.Eventf(ing, corev1.EventTypeWarning, "InvalidIngressBackend", "rule with host %q ignored, unsupported", rule.Host) a.recorder.Eventf(ing, corev1.EventTypeWarning, "InvalidIngressBackend", "rule with host %q ignored, unsupported", rule.Host)
continue continue
} }
@ -253,10 +259,9 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
tags = strings.Split(tstr, ",") tags = strings.Split(tstr, ",")
} }
hostname := ing.Namespace + "-" + ing.Name + "-ingress" hostname := ing.Namespace + "-" + ing.Name + "-ingress"
if tlsHost != "" { // if tlsHost != "" {
hostname, _, _ = strings.Cut(tlsHost, ".") // hostname, _, _ = strings.Cut(tlsHost, ".")
} // }
sts := &tailscaleSTSConfig{ sts := &tailscaleSTSConfig{
Hostname: hostname, Hostname: hostname,
ParentResourceName: ing.Name, ParentResourceName: ing.Name,
@ -265,6 +270,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
Tags: tags, Tags: tags,
ChildResourceLabels: crl, ChildResourceLabels: crl,
ProxyClass: proxyClass, ProxyClass: proxyClass,
TSVIP: a.tailnetVIPForIngress(ing),
} }
if val := ing.GetAnnotations()[AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy]; val == "true" { if val := ing.GetAnnotations()[AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy]; val == "true" {
@ -307,6 +313,13 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
return nil return nil
} }
func (a *IngressReconciler) tailnetVIPForIngress(ing *networkingv1.Ingress) string {
if !a.shouldExpose(ing) || ing.Annotations == nil {
return ""
}
return ing.GetAnnotations()[AnnotationTSVIP]
}
func (a *IngressReconciler) shouldExpose(ing *networkingv1.Ingress) bool { func (a *IngressReconciler) shouldExpose(ing *networkingv1.Ingress) bool {
return ing != nil && return ing != nil &&
ing.Spec.IngressClassName != nil && ing.Spec.IngressClassName != nil &&

@ -428,7 +428,7 @@ var userspaceProxyYaml []byte
func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.SugaredLogger, sts *tailscaleSTSConfig, headlessSvc *corev1.Service, proxySecret, tsConfigHash string) (*appsv1.StatefulSet, error) { func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.SugaredLogger, sts *tailscaleSTSConfig, headlessSvc *corev1.Service, proxySecret, tsConfigHash string) (*appsv1.StatefulSet, error) {
ss := new(appsv1.StatefulSet) ss := new(appsv1.StatefulSet)
if sts.ServeConfig != nil && sts.ForwardClusterTrafficViaL7IngressProxy != true { // If forwarding cluster traffic via is required we need non-userspace + NET_ADMIN + forwarding if sts.ServeConfig != nil && sts.ForwardClusterTrafficViaL7IngressProxy != true && sts.TSVIP == "" { // If forwarding cluster traffic via is required we need non-userspace + NET_ADMIN + forwarding
if err := yaml.Unmarshal(userspaceProxyYaml, &ss); err != nil { if err := yaml.Unmarshal(userspaceProxyYaml, &ss); err != nil {
return nil, fmt.Errorf("failed to unmarshal userspace proxy spec: %v", err) return nil, fmt.Errorf("failed to unmarshal userspace proxy spec: %v", err)
} }

@ -3299,9 +3299,13 @@ func (b *LocalBackend) handlePeerAPIConn(remote, local netip.AddrPort, c net.Con
return return
} }
func (b *LocalBackend) isLocalIP(ip netip.Addr) bool { func (b *LocalBackend) isLocallyAvailable(ip netip.Addr) bool {
nm := b.NetMap() nm := b.NetMap()
return nm != nil && views.SliceContains(nm.GetAddresses(), netip.PrefixFrom(ip, ip.BitLen())) if nm == nil {
return false
}
pfx := netip.PrefixFrom(ip, ip.BitLen())
return views.SliceContains(nm.SelfNode.AllowedIPs(), pfx)
} }
var ( var (
@ -3319,7 +3323,7 @@ func (b *LocalBackend) TCPHandlerForDst(src, dst netip.AddrPort) (handler func(c
} }
return b.HandleQuad100Port80Conn, opts return b.HandleQuad100Port80Conn, opts
} }
if !b.isLocalIP(dst.Addr()) { if !b.isLocallyAvailable(dst.Addr()) {
return nil, nil return nil, nil
} }
if dst.Port() == 22 && b.ShouldRunSSH() { if dst.Port() == 22 && b.ShouldRunSSH() {

Loading…
Cancel
Save