Servis keşfi

Servis keşfi

Bir discovery provider, dış sistemdeki proxy tanımlarını okur ve proxy listesine ekler. Bir tanım değişince r3v3rs3 route'ları restart olmadan günceller.

Bu sayfa referanstır. Docker label'larıyla çalışan bir kurulum için Docker'dan proxy'ler rehberini izleyin.

Keşfedilen proxy'ler

Provider durumu

Proxy listesi her provider'ın durumunu, eklediği proxy sayısını ve proxy olamayan tanımları gösterir. Admin API aynı veriyi GET /api/discovery adresinde döner.

DurumAnlamı
connectingProvider kaynaklarını henüz okumadı.
runningProvider kaynaklarını okudu ve değişiklikleri izliyor.
errorProvider kaynaklarını okuyamıyor. Son okumasındaki proxy'ler aktif kalır.

Bir issue kaynağı ve sebebi verir, örneğin web-1: http.app: port not found: https.

Label'lar

Docker label'ları, Consul tag'leri ve key-value kayıtları aynı key'leri kullanır. Her key şu biçimdedir:

r3v3rs3.<protocol>.<name>.<field>=<value>

Proxy key'leri

KeyDeğer
r3v3rs3.enableProvider her kaynağı okumuyorsa true kaynağı seçer.
portsZorunlu. Virgülle ayrılmış port adları veya port id'leri.
nameProxy listesindeki ad. Varsayılan değer <name> olur.
activefalse proxy'yi pasif olarak ekler. Varsayılan değer true olur.
portKaynağın adresindeki upstream server'ın portu.
schemeHTTP proxy'nin port alanı için http veya https. Varsayılan değer http olur.
acmeHTTP proxy'nin vhosts alanı için sertifika alan ACME kaydının id'si. ACME sertifikaları bölümüne bakın.

Değerler

HTTP proxy'ler

port ve scheme, / path'ine tek server'lı bir route tanımlar. routes ile birlikte kullanılamaz.

r3v3rs3.http.app.ports=https
r3v3rs3.http.app.vhosts=app.example.com
r3v3rs3.http.app.port=8080

Bir route da port ve scheme kullanabilir. Aynı route'un servers alanıyla birlikte kullanılamaz.

r3v3rs3.http.app.ports=http,https
r3v3rs3.http.app.vhosts=app.example.com
r3v3rs3.http.app.routes.0.path=/
r3v3rs3.http.app.routes.0.port=8080
r3v3rs3.http.app.routes.1.path=/api
r3v3rs3.http.app.routes.1.port=9443
r3v3rs3.http.app.routes.1.scheme=https

Server'a açık bir URL ve weight verilebilir:

r3v3rs3.http.app.routes.0.servers.0.url=http://10.0.0.5:8080
r3v3rs3.http.app.routes.0.servers.1.url=http://10.0.0.6:8080
r3v3rs3.http.app.routes.0.servers.1.weight=3
r3v3rs3.http.app.load_balancing=round_robin

Diğer alanlar admin API adlarını kullanır:

r3v3rs3.http.app.upgrade_insecure=true
r3v3rs3.http.app.ip_filter.allow=10.0.0.0/8,192.168.0.0/16
r3v3rs3.http.app.rate_limit.requests=100
r3v3rs3.http.app.rate_limit.per=minute
r3v3rs3.http.app.rate_limit.burst=20
r3v3rs3.http.app.timeouts.connect=3s
r3v3rs3.http.app.timeouts.request=30s
r3v3rs3.http.app.health_check.interval=10s
r3v3rs3.http.app.health_check.path=/healthz
r3v3rs3.http.app.compression.algorithms=br,gzip
r3v3rs3.http.app.cache.enabled=true
r3v3rs3.http.app.cache.default_ttl=1m
r3v3rs3.http.app.headers.response.0.action=set
r3v3rs3.http.app.headers.response.0.name=X-Frame-Options
r3v3rs3.http.app.headers.response.0.value=DENY
r3v3rs3.http.app.auth.type=basic
r3v3rs3.http.app.auth.realm=Staff
r3v3rs3.http.app.auth.users.0.username=alice
r3v3rs3.http.app.auth.users.0.password=change-me

r3v3rs3, proxy'yi kullanmadan önce düz metin password ve token değerlerini hash'e çevirir. Kaynak düz metin değeri tutmaya devam eder. Bu yüzden label'larda password_hash ve token_hash tercih edin.

TCP ve UDP proxy'ler

port, kaynağın adresinde tek bir upstream server tanımlar. upstream_servers ile birlikte kullanılamaz.

r3v3rs3.tcp.db.ports=postgres
r3v3rs3.tcp.db.port=5432

r3v3rs3.udp.dns.ports=dns
r3v3rs3.udp.dns.upstream_servers.0.addr=/ip4/10.0.0.53/udp/53
r3v3rs3.udp.dns.session_idle_timeout=30s

ACME sertifikaları

acme, sertifika listesindeki mevcut bir ACME kaydını verir. r3v3rs3, kaydın account'u, challenge'ı ve DNS provider'ı ile proxy'nin virtual host'ları için sertifika alır.

r3v3rs3.http.app.ports=https
r3v3rs3.http.app.vhosts=app.example.com,www.example.com
r3v3rs3.http.app.port=8080
r3v3rs3.http.app.acme=abc-def

Docker

Docker provider, çalışan container'ların label'larını Docker Engine API ile okur. Container event'lerini izler. Başlayan, duran veya değişen bir container proxy'leri yaklaşık bir saniye içinde günceller.

Ayarlar

"Ayarlar" sayfasında "Docker Servis Keşfi" bölümünü doldurun veya config.toml dosyasını düzenleyin:

[discovery.docker]
enabled = true
endpoint = "unix:///var/run/docker.sock"
network = "proxy"
exposed_by_default = false
AyarAnlamı
enabledProvider'ı başlatır.
endpointunix://<path>, tcp://<host>:<port>, http://<host>:<port> veya https://<host>:<port>. Varsayılan değer unix:///var/run/docker.sock olur.
client_certr3v3rs3'ün https endpoint'ine gönderdiği client sertifikasının id'si. Server sertifikasını bir sistem root sertifikası veya r3v3rs3'teki bir root sertifika imzalamalıdır.
networkUpstream adreslerinin alındığı Docker network'ü. Her container tek network'e bağlıysa boş bırakın.
exposed_by_defaulttrue, r3v3rs3. label'ı olan her container'ı okur. false yalnız r3v3rs3.enable=true olan container'ları okur.

Ayar değişikliği provider'ı server restart olmadan yeniden başlatır. Provider'ın kullandığı sertifika silinemez.

Container'lar

Compose örneği

services:
  r3v3rs3:
    image: ghcr.io/kilimcininkoroglu/r3v3rs3:latest
    volumes:
      - r3v3rs3-config:/root/.config/r3v3rs3
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks: [proxy]
    ports:
      - 80:80
      - 127.0.0.1:46492:46492

  whoami:
    image: traefik/whoami
    networks: [proxy]
    labels:
      r3v3rs3.enable: "true"
      r3v3rs3.http.whoami.ports: http
      r3v3rs3.http.whoami.vhosts: whoami.example.com
      r3v3rs3.http.whoami.port: "80"

networks:
  proxy:
    name: proxy

volumes:
  r3v3rs3-config:

"Portlar" sayfasında http adında bir port ekleyin, provider'ı proxy network'ü ile açın ve stack'i başlatın. Network name alanını vermezse Compose network adının başına proje adını ekler.

Docker socket erişimi Docker host'unun tam kontrolünü verir. Bu yetki root erişimine eşittir. :ro seçeneği yalnız socket dosyasına uygulanır ve API'yi salt okunur yapmaz. Yönetim paneline veya host'a güvenilmeyen network'lerden erişilebiliyorsa r3v3rs3'ü yalnız GET /containers/json ve GET /events isteklerine izin veren bir Docker socket proxy'sine bağlayın.

Kubernetes

Kubernetes provider, networking.k8s.io/v1 Ingress kaynaklarını, r3v3rs3.io/v1 R3v3rs3Proxy kaynaklarını, backend'lerinin Service ve EndpointSlice'larını ve Ingress kaynaklarının TLS secret'larını okur. Değişiklikleri watch stream'leriyle izler. Değişen bir kaynak, hazır hale gelen yeni bir pod veya yenilenen bir secret proxy'leri yaklaşık bir saniye içinde günceller.

deploy/kubernetes dizininde custom resource definition (crd.yaml), service account ve ClusterRole'ü (rbac.yaml) ve örnek bir Deployment (deployment.yaml) bulunur.

Ayarlar

"Ayarlar" sayfasında "Kubernetes Servis Keşfi" bölümünü doldurun veya config.toml dosyasını düzenleyin:

[discovery.kubernetes]
enabled = true
kubeconfig = ""
namespaces = []
ingress = true
crd = true
ingress_class = "r3v3rs3"
ports = ["http"]
AyarAnlamı
enabledProvider'ı başlatır.
kubeconfigKubeconfig dosyasının yolu. KUBECONFIG değişkenini veya ~/.kube/config dosyasını kullanmak için boş bırakın. Cluster içinde boş değer pod'un service account'unu kullanır.
namespacesOkunacak namespace'ler. Her namespace'i okumak için boş bırakın.
ingressIngress kaynaklarını okur. Varsayılan değer true olur.
crdR3v3rs3Proxy kaynaklarını okur. Varsayılan değer false olur. Önce custom resource definition'ı kurun, çünkü provider cluster'ın tanımadığı bir kaynağı watch edemez. Provider ingress veya crd ayarını gerektirir.
ingress_classr3v3rs3 yalnız bu class'ın Ingress kaynaklarını okur. Class, spec.ingressClassName alanından veya kubernetes.io/ingress.class annotation'ından gelir. Her Ingress'i okumak için boş bırakın.
portsr3v3rs3.io/ports annotation'ı olmayan bir Ingress'in kullandığı port adları veya id'leri.

Ayar değişikliği provider'ı server restart olmadan yeniden başlatır.

Ingress kaynakları

Annotation'lar

r3v3rs3.io/<field> annotation'ı Ingress'in proxy'lerinde bir alanı ayarlar. Alanlar ve değerler, Label'lar bölümündeki HTTP proxy alanlarıdır. r3v3rs3.http.<name>. prefix'i yazılmaz.

AnnotationAnlamı
r3v3rs3.io/portsProxy'lerin port adları veya id'leri. ports ayarının yerine geçer. Bu annotation'ı ve ayarı olmayan Ingress issue olur.
r3v3rs3.io/nameProxy'lerin adı.
r3v3rs3.io/acmeHer host için sertifika alan ACME kaydı. ACME sertifikaları bölümüne bakın.
r3v3rs3.io/<field>Diğer her alan, örneğin r3v3rs3.io/rate_limit.requests veya r3v3rs3.io/headers.response.0.name.

routes ve vhosts alanlarını Ingress kuralları ayarlar. Bu yüzden routes, vhosts, port veya scheme annotation'ı issue olur.

TLS secret'ları

R3v3rs3Proxy kaynakları

Bir R3v3rs3Proxy kaynağı, proxy modelinin alanlarıyla bir proxy tanımlar. Bu yüzden TCP veya UDP proxy de tanımlayabilir ve her alanı ayarlayabilir. Önce definition'ı kurun, sonra crd ayarını açın:

kubectl apply -f deploy/kubernetes/crd.yaml
apiVersion: r3v3rs3.io/v1
kind: R3v3rs3Proxy
metadata:
  name: whoami
  namespace: default
spec:
  ports: [https]
  vhosts: [whoami.example.com]
  rate_limit:
    requests: 100
    per: minute
  routes:
    - path: /
      service:
        name: whoami
        port: http
---
apiVersion: r3v3rs3.io/v1
kind: R3v3rs3Proxy
metadata:
  name: postgres
  namespace: default
spec:
  protocol: tcp
  ports: [postgres]
  service:
    name: postgres
    port: 5432

RBAC

Provider beş kaynağı list ve watch eder. deploy/kubernetes/rbac.yaml dosyası bu nesneleri içerir. r3v3rs3'ün service account'una bir ClusterRole verin veya namespaces ayarındaki her namespace'te bir Role verin:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: r3v3rs3
  namespace: r3v3rs3
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: r3v3rs3
rules:
  - apiGroups: ["networking.k8s.io"]
    resources: ["ingresses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["services", "secrets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["discovery.k8s.io"]
    resources: ["endpointslices"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["r3v3rs3.io"]
    resources: ["r3v3rs3proxies"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: r3v3rs3
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: r3v3rs3
subjects:
  - kind: ServiceAccount
    name: r3v3rs3
    namespace: r3v3rs3

Provider yalnız kubernetes.io/tls tipindeki secret'ları okur. Kubernetes RBAC ise list iznini tipe göre sınırlayamaz. Bu yüzden rol, r3v3rs3'ün namespace'lerindeki bütün secret'ları okumasına izin verir. Bu erişimi sınırlamak için namespaces ayarını ve her namespace'te bir Role kullanın.

Ingress örneği

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: whoami
  namespace: default
  annotations:
    r3v3rs3.io/ports: https
    r3v3rs3.io/headers.response.0.action: set
    r3v3rs3.io/headers.response.0.name: X-Frame-Options
    r3v3rs3.io/headers.response.0.value: DENY
spec:
  ingressClassName: r3v3rs3
  tls:
    - hosts: [whoami.example.com]
      secretName: whoami-tls
  rules:
    - host: whoami.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: whoami
                port:
                  name: http

"Portlar" sayfasında https adında bir TLS portu ekleyin. r3v3rs3 pod adreslerine erişebilmelidir. Bu yüzden r3v3rs3'ü cluster içinde veya cluster'ın bir node'unda çalıştırın.

Consul

Consul provider, catalog'daki servislerin r3v3rs3.* tag'lerini ve key-value store'da bir prefix'in altındaki key'leri okur. Değişiklikleri blocking query'lerle izler. Kaydedilen, silinen veya health check'i başarısız olan bir servis instance'ı ve değişen bir key proxy'leri yaklaşık bir saniye içinde günceller.

Ayarlar

"Ayarlar" sayfasında "Consul Servis Keşfi" bölümünü doldurun veya config.toml dosyasını düzenleyin:

[discovery.consul]
enabled = true
address = "http://127.0.0.1:8500"
token = "<ACL token>"
catalog = true
kv = true
prefix = "r3v3rs3"
exposed_by_default = false
AyarAnlamı
enabledProvider'ı başlatır.
addressBir Consul agent'ının HTTP API'si: http://<host>:<port>, https://<host>:<port> veya unix://<path>. Varsayılan değer http://127.0.0.1:8500 olur.
client_certr3v3rs3'ün https adresine gönderdiği client sertifikasının id'si.
tokenACL token'ı. Catalog için service:read ve node:read, key-value store için prefix üzerinde key:read izni gerekir.
datacenterOkunacak datacenter. Agent'ın kendi datacenter'ını okumak için boş bırakın.
catalogCatalog'daki servislerin tag'lerini okur. Varsayılan değer true olur.
kvprefix altındaki key'leri okur. Varsayılan değer true olur.
prefixKey prefix'i. Varsayılan değer r3v3rs3 olur.
exposed_by_defaulttrue, r3v3rs3. tag'i olan her servisi okur. false yalnız r3v3rs3.enable=true tag'i olan servisleri okur.

Admin API token'ı döndürmez. Kayıtlı bir token varsa GET /api/config yanıtında token_set: true döner. token alanı olmayan bir PUT /api/config isteği kayıtlı token'ı korur. "token": "" token'ı siler. config.toml token'ı düz metin olarak saklar. Bu yüzden config dizinini yalnız r3v3rs3 kullanıcısı okuyabilmelidir.

Catalog servisleri

Servisi Consul agent'ına kaydedin, örneğin consul services register whoami.json komutuyla:

{
  "Service": {
    "Name": "whoami",
    "Port": 8080,
    "Tags": [
      "r3v3rs3.enable=true",
      "r3v3rs3.http.whoami.ports=http",
      "r3v3rs3.http.whoami.vhosts=whoami.example.com"
    ],
    "Check": { "HTTP": "http://localhost:8080/", "Interval": "10s" }
  }
}

Key-value store

consul kv put r3v3rs3/http/app/ports https
consul kv put r3v3rs3/http/app/vhosts app.example.com
consul kv put r3v3rs3/http/app/routes/0/servers/0/url http://10.0.0.5:8080

etcd

etcd provider, bir prefix'in altındaki key'leri etcd v3 HTTP API'si ile okur. Değişiklikleri bir watch stream'i ile izler. Değişen bir key proxy'leri yaklaşık bir saniye içinde günceller.

Ayarlar

"Ayarlar" sayfasında "etcd Servis Keşfi" bölümünü doldurun veya config.toml dosyasını düzenleyin:

[discovery.etcd]
enabled = true
endpoints = ["http://10.0.0.1:2379", "http://10.0.0.2:2379"]
username = "r3v3rs3"
password = "<password>"
prefix = "r3v3rs3"
AyarAnlamı
enabledProvider'ı başlatır.
endpointsCluster üyelerinin HTTP API adresleri: http://<host>:<port>, https://<host>:<port> veya unix://<path>. Bağlantı başarısız olunca r3v3rs3 sıradaki adrese bağlanır. Varsayılan değer http://127.0.0.1:2379 olur.
client_certr3v3rs3'ün https endpoint'ine gönderdiği client sertifikasının id'si.
usernameetcd authentication kullanıcısı. Authentication kapalıysa boş bırakın.
passwordKullanıcının parolası. username ile birlikte verin.
prefixKey prefix'i. Varsayılan değer r3v3rs3 olur.

Admin API parolayı döndürmez. Kayıtlı bir parola varsa GET /api/config yanıtında password_set: true döner. password alanı olmayan bir PUT /api/config isteği kayıtlı parolayı korur. "password": "" parolayı siler. config.toml parolayı düz metin olarak saklar. Bu yüzden config dizinini yalnız r3v3rs3 kullanıcısı okuyabilmelidir.

Authentication açıksa r3v3rs3 kullanıcı adı ve parola ile bir token alır. etcd süresi dolmuş bir token'ı reddedince r3v3rs3 yeni bir token alır ve isteği yeniden gönderir. Kullanıcının prefix üzerinde okuma izni olan bir rolü olmalıdır:

etcdctl role add r3v3rs3-reader
etcdctl role grant-permission r3v3rs3-reader --prefix=true read r3v3rs3/
etcdctl user add r3v3rs3
etcdctl user grant-role r3v3rs3 r3v3rs3-reader

Key'ler

etcdctl put r3v3rs3/http/app/ports https
etcdctl put r3v3rs3/http/app/vhosts app.example.com
etcdctl put r3v3rs3/http/app/routes/0/servers/0/url http://10.0.0.5:8080