XTLS / Xray-core

Xray, Penetrates Everything. Also the best v2ray-core, with XTLS support. Fully compatible configuration.
https://t.me/projectXray
Mozilla Public License 2.0
23.16k stars 3.71k forks source link

请问怎么在K3S中安装xray并开启reality功能? #2122

Closed fanite closed 1 year ago

fanite commented 1 year ago

在K3s环境中使用traefik作为反向代理

{
      "log": {
        "loglevel": "info"
      },
      "api": {
        "tag": "api",
        "services": [
          "HandlerService",
          "LoggerService",
          "StatsService"
        ]
      },
      "stats": {},
      "policy": {
        "levels": {
          "0": {
            "statsUserUplink": true,
            "statsUserDownlink": true
          }
        },
        "system": {
          "statsInboundUplink": true,
          "statsInboundDownlink": true,
          "statsOutboundUplink": true,
          "statsOutboundDownlink": true
        }
      },
      "dns": {
        "servers": [
          "https+local://cloudflare-dns.com/dns-query",
          "1.1.1.1",
          "1.0.0.1",
          "8.8.8.8",
          "8.8.4.4",
          "localhost"
        ]
      },
      "inbounds": [
        {
          "listen": "0.0.0.0",
          "port": 443,
          "protocol": "vless",
          "settings": {
            "clients": [
              {
                "id": "a105cb44-d85d-4f76-a6d0-fcfae2319010",
                "flow": "xtls-rprx-vision"
              }
            ],
            "decryption": "none",
            "fallbacks": [
              {
                "dest": 2005,
                "xver": 1
              }
            ]
          },
          "sockopt": {
            "acceptProxyProtocol": true
          },
          "streamSettings": {
            "network": "tcp",
            "security": "reality",
            "realitySettings": {
              "show": true,
              "dest": "example.com:443",
              "xver": 1,
              "maxTimeDiff": 0,
              "minClientVer": "",
              "serverNames": [
                "example.com"
              ],
              "privateKey": "AE31bVkXmiDdMVeFDMd90AdRdPPzcOot6y5nF70W91U",
              "shortIds": [
                "10",
                "1008",
                "100861",
                "10086100",
                "1008610086"
              ]
            }
          },
          "sniffing": {
            "enabled": true,
            "destOverride": [
              "http",
              "tls"
            ]
          }
        },
        {
          "listen": "0.0.0.0",
          "port": 2005,
          "protocol": "vless",
          "settings": {
            "clients": [
              {
                "id": "a105cb44-d85d-4f76-a6d0-fcfae2319010",
                "email": "2005@gmail.com"
              }
            ],
            "decryption": "none"
          },
          "streamSettings": {
            "network": "h2",
            "security": "none",
            "sockopt": {
              "acceptProxyProtocol": true
            }
          },
          "sniffing": {
            "enabled": true,
            "destOverride": [
              "http",
              "tls"
            ]
          }
        }
      ],
      "outbounds": [
        {
          "protocol": "freedom",
          "tag": "direct"
        },
        {
          "protocol": "blackhole",
          "tag": "blocked"
        },
        {
          "protocol": "freedom",
          "tag":"IPv4_OUT"
        },
        {
          "protocol": "freedom",
          "tag":"IPv6_OUT",
          "settings": {
            "domainStrategy": "UseIPv6"
          }
        }
      ],
      "routing": {
        "domainStrategy": "IPIfNonMatch",
        "rules": [
          {
            "inboundTag": [
              "api"
            ],
            "outboundTag": "api",
            "type": "field"
          },
          {
            "domain": [
              "domain:iqiyi.com",
              "domain:video.qq.com",
              "domain:youku.com"
            ],
            "type": "field",
            "outboundTag": "blocked"
          },
          {
            "type": "field",
            "ip": [
              "geoip:cn",
              "geoip:private"
            ],
            "outboundTag": "blocked"
          },
          {
            "protocol": [
              "bittorrent"
            ],
            "type": "field",
            "outboundTag": "blocked"
          },
          {
              "type": "field",
              "domain": [
                "netflix.com",
                "netflix.net",
                "netflixdnstest1.com",
                "netflixdnstest2.com",
                "netflixdnstest3.com",
                "netflixdnstest4.com",
                "netflixdnstest5.com",
                "netflixdnstest6.com",
                "netflixdnstest7.com",
                "netflixdnstest8.com",
                "netflixdnstest9.com",
                "netflixdnstest10.com",
                "netflixinvestor.com",
                "netflixtechblog.com",
                "nflxext.com",
                "nflximg.com",
                "nflximg.net",
                "nflxsearch.net",
                "nflxso.net",
                "nflxvideo.net",
                "geosite:netflix",
                "geosite:google",
                "geosite:youtube"
              ],
              "outboundTag": "IPv6_OUT"
            },
            {
              "type": "field",
              "outboundTag": "IPv4_OUT",
              "network": "udp,tcp"
            }
        ]
      }
    }

ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: xray
  labels:
    helm.sh/chart: xray-0.1.0
    app.kubernetes.io/name: xray
    app.kubernetes.io/instance: xray
    app.kubernetes.io/version: "1.8.1"
    app.kubernetes.io/managed-by: Helm
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: web,websecure
    traefik.ingress.kubernetes.io/router.middlewares: kube-system-redirect-https@kubernetescrd
    cert-manager.io/cluster-issuer: letsencrypt-production-http
spec:
  ingressClassName: traefik
  tls:
    - hosts:
      - example.com
      secretName: xray-tls
  rules:
    - host: example.com
      http:
        paths:
        - path: "/yearn"
          pathType: Prefix
          backend:
            service:
              name: xray
              port:
                name: xray-core
        - path: /
          pathType: Prefix
          backend:
            service:
              name: xray-mask
              port:
                name: xray-mask

错误提示:

x509: certificate signed by unknown authority
guigeng commented 1 year ago

你要使用traefik的IngressRouteTCP功能 以下根据自己配置调整,实测可用。我服务端用的sing-box可以。目前在测试dest设置为k3s内建一个nextcloud网站,serverName为每个节点一个域名的方法。

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: # 设置路由名称
  namespace: proxy
spec:
  entryPoints:
    - websecure
  routes:
    - match: HostSNI(`example.com`)
      services:
        - name: 服务名称
          port: 443 # 服务监听端口
          proxyProtocol:
            version: 2
  tls:
    passthrough: true
fanite commented 1 year ago

你要使用traefik的IngressRouteTCP功能 以下根据自己配置调整,实测可用。我服务端用的sing-box可以。目前在测试dest设置为k3s内建一个nextcloud网站,serverName为每个节点一个域名的方法。

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: # 设置路由名称
  namespace: proxy
spec:
  entryPoints:
    - websecure
  routes:
    - match: HostSNI(`example.com`)
      services:
        - name: 服务名称
          port: 443 # 服务监听端口
          proxyProtocol:
            version: 2
  tls:
    passthrough: true

可以发一下你的具体配置吗

guigeng commented 1 year ago

你要使用traefik的IngressRouteTCP功能 以下根据自己配置调整,实测可用。我服务端用的sing-box可以。目前在测试dest设置为k3s内建一个nextcloud网站,serverName为每个节点一个域名的方法。

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: # 设置路由名称
  namespace: proxy
spec:
  entryPoints:
    - websecure
  routes:
    - match: HostSNI(`example.com`)
      services:
        - name: 服务名称
          port: 443 # 服务监听端口
          proxyProtocol:
            version: 2
  tls:
    passthrough: true

可以发一下你的具体配置吗

reality 的serverName和dest要相同,还要忽略证书 不同的域名不行。没测通

用trojan grpc和vmess grpc没问题

guigeng commented 1 year ago

你要使用traefik的IngressRouteTCP功能 以下根据自己配置调整,实测可用。我服务端用的sing-box可以。目前在测试dest设置为k3s内建一个nextcloud网站,serverName为每个节点一个域名的方法。

apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: # 设置路由名称
  namespace: proxy
spec:
  entryPoints:
    - websecure
  routes:
    - match: HostSNI(`example.com`)
      services:
        - name: 服务名称
          port: 443 # 服务监听端口
          proxyProtocol:
            version: 2
  tls:
    passthrough: true

可以发一下你的具体配置吗

注意,用xray没测通,用sing-box测通了 k3s configMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: proxy-reality
  namespace: proxy
data:
  config.json: |
    {
        "log": {
            "disabled": false,
            "level": "info",
            "timestamp": true
        },
        "inbounds": [
            {
                "type": "vless",
                "tag": "vless-grpc",
                "listen": "::",
                "listen_port": 8003,
                "sniff": true,
                "sniff_override_destination": true,
                "domain_strategy": "ipv4_only",
                "proxy_protocol": true,
                "proxy_protocol_accept_no_header": false,
                "users": [
                    {
                        "uuid": "", // 或执行 ./sing-box generate uuid 生成
                        "flow": "" // 留空
                    }
                ],
                "tls": {
                    "enabled": true,
                    "server_name": "www.docker.com", // 客户端可用的 serverName 列表,暂不支持 * 通配符
                    "reality": {
                        "enabled": true,
                        "handshake": {
                            "server": "www.docker.com", // 目标网站最低标准:国外网站,支持 TLSv1.3、X25519 与 H2,域名非跳转用(主域名可能被用于跳转到 www)
                            "server_port": 443
                        },
                        "private_key": "", // 执行 ./sing-box generate reality-keypair 生成,填 "Privatekey" 的值
                        "short_id": [ // 客户端可用的 shortId 列表,可用于区分不同的客户端
                            "" // 0 到 f,长度为 2 的倍数,长度上限为 16,可留空,或执行 ./sing-box generate rand --hex 8 生成
                        ]
                    }
                },
                "transport": {
                    "type": "grpc",
                    "service_name": "" // 指定服务名称
                }
            }
        ],
        "outbounds": [
            {
                "type": "direct",
                "tag": "direct-out"
            }
        ]
    }

k3s无头服务和部署StatefulSet

apiVersion: v1
kind: Service
metadata:
  name: proxy-reality
  namespace: proxy
  labels:
    app: xray
spec:
  ports:
    - port: 8003
      name: reality-grpc
  clusterIP: None
  selector:
    app: xray
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: superportal-reality
  namespace: proxy
  labels:
    app: xray
spec:
  serviceName: "proxy-reality"
  replicas: 1
  selector:
    matchLabels:
      app: xray
  template:
    metadata:
      labels:
        app: xray
    spec:
      nodeSelector: 
        kubernetes.io/hostname: node-jp  # 固定到节点

      containers:
        - name: xray
          image:  # sing-box 镜像
          command: ["sing-box"]
          args: ["run", "-c", "/etc/xray/config.json"]
          ports:
            - containerPort: 8003
              name: reality-grpc
          volumeMounts:
            - name: xray-config
              mountPath: /etc/xray/
              readOnly: true
      volumes:
        - name: xray-config
          configMap:
            name: proxy-reality

创建Traefik TCP路由

    cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: sing-box-8003
  namespace: proxy
spec:
  type: ExternalName
  ## 域名,或者 直接能用ip和端口直接访问的
  externalName: superportal-reality-0.proxy-reality.proxy
  ports:
    - port: 8003
---
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
  name: sing-box-8003
  namespace: proxy
spec:
  entryPoints:
    - websecure
  routes:
    - match: HostSNI(\`www.docker.com\`)
      services:
        - name: sing-box-8003
          port: 8003
          proxyProtocol:
            version: 2
  tls:
    passthrough: true
guigeng commented 1 year ago

xray应该是漏掉下面这个,导致不通

                "sockopt": {
                    "acceptProxyProtocol": true
                }
fanite commented 1 year ago

xray应该是漏掉下面这个,导致不通

                "sockopt": {
                    "acceptProxyProtocol": true
                }

搞不定,traefik+xray+reality这种方式可能是真的不行 /(ㄒoㄒ)/~~

guigeng commented 1 year ago

sinh-box没问题。 目前做法是sing-box+nginx泛域名证书。用自带证书实现。再套cdn,reality grpc。浏览器访问域名走cf访问网站,客户端设置网站sni正常扶墙 一个pod里面2个容器解决,前端traefik hostsni分流

fanite commented 1 year ago
proxyProtocol:
            version: 2
xver: 0

我的可以了。代理协议需要选择0,1和2都不行,不懂是什么原因

johnsmzr commented 7 months ago
proxyProtocol:
            version: 2
xver: 0

我的可以了。代理协议需要选择0,1和2都不行,不懂是什么原因

可以分享一下具体配置吗?谢谢

ztmzzz commented 1 month ago

我使用的是nginx-ingress,以下是已经测试成功的配置。要求先开启nginx-ingress的ssl-passthrough功能。 config.json

{
  "log": {
    "loglevel": "warning",
    "error": "/var/log/xray/error.log"
  },
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "geosite:cn",
          "geoip:private"
        ],
        "outboundTag": "block"
      }
    ]
  },
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "你自己的",
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "tcpSettings": {
          "acceptProxyProtocol": false #ingress中没有开启ProxyProtocol功能
        },
        "security": "reality",
        "realitySettings": {
          "show": false,
          "dest": "www.samsung.com:443",
          "xver": 0,
          "serverNames": [
            "www.samsung.com"
          ],
          "privateKey": "你自己的",
          "minClientVer": "",
          "maxClientVer": "",
          "maxTimeDiff": 0,
          "shortIds": [
            "你自己的"
          ]
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls"
        ]
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "freedom",
      "tag": "direct"
    },
    {
      "protocol": "blackhole",
      "tag": "block"
    }
  ]
}

k8s配置

kind: Deployment
apiVersion: apps/v1
metadata:
  name: xray-deployment
  namespace: vpn
spec:
  replicas: 1
  selector:
    matchLabels:
      app: xray
  template:
    metadata:
      labels:
        app: xray
    spec:
      volumes:
        - name: config
          secret:
            secretName: config-secret
      containers:
        - name: xray
          image: ghcr.io/xtls/xray-core:latest
          ports:
            - name: port
              containerPort: 443
              protocol: TCP
          resources: {}
          volumeMounts:
            - name: config
              readOnly: true
              mountPath: /etc/xray/config.json
              subPath: config.json
      dnsPolicy: Default #走机器自己的dns
      nodeName: bwh #设置节点
----------------------------
kind: Service
apiVersion: v1
metadata:
  name: xray-service
  namespace: vpn
spec:
  ports:
    - protocol: TCP
      port: 443
      targetPort: 443
  selector:
    app: xray
----------------------------
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: xray-ingress
  namespace: vpn
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/ssl-passthrough: 'true'
spec:
  ingressClassName: public
  rules:
    - host: www.samsung.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: xray-service
                port:
                  number: 443
johnsmzr commented 1 month ago

@ztmzzz 非常感谢!!🙏