k8s安装openvpn(ldap)

Posted by Naah on Monday, Jul 26,2021 18:15:50

1 安装helm3.0

略过

2 下载charts

git clone https://hub.fastgit.org/helm/charts.git

3 安装openvpn

安装openvpn需要持久卷,没有可以安装一个nfs的默认存储类

3.1 进入openvpn目录

cd /root/helm/charts/stable/openvpn

3.2 修改configmap

cd /root/helm/charts/stable/openvpn/templates
vi config-openvpn.yaml

3.2.1 修改configure.sh

在最后一行exec ...前加入以下行

# 加入ldap插件
apk add openvpn-auth-ldap --update-cache --repository http://dl-4.alpinelinux.org/alpine/edge/main/

# 开启ip转发
sysctl -w net.ipv4.ip_forward=1

3.2.2 修改openvpn.conf

在最后加入以下行,开启ldap和客户端忽略cert

plugin /usr/lib/openvpn/plugins/openvpn-auth-ldap.so "/etc/openvpn/setup/auth-ldap.conf uid=%u" 

client-cert-not-required

3.2.3 加入新配置文件auth-ldap.conf

<LDAP>
        URL             ldap://你的ldapurl
        BindDN                你的用来登陆验证的ldap账号
        Password      ldap账号密码
        Timeout         15
        TLSEnable       no
        FollowReferrals no
</LDAP>
<Authorization>
        BaseDN          "ldap用户的基础路径"
        SearchFilter    "uid=%u"
        RequireGroup    true
        <Group>
                BaseDN          "组的base目录"
                SearchFilter    "(cn=openvpn)"
                MemberAttribute uniqueMember
        </Group>
</Authorization>

3.2.4 最终配置

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ template "openvpn.fullname" . }}
  labels:
    app: {{ template "openvpn.name" . }}
    chart: {{ template "openvpn.chart" . }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
data:
  auth-ldap.conf: |-
    <LDAP>
            URL             ldap://10.247.30.15
            BindDN                cn=readonly,dc=mindflow,dc=com
            Password      mindflowreadonly
            Timeout         15
            TLSEnable       no
            FollowReferrals no
    </LDAP>
    <Authorization>
            BaseDN          "ou=users,dc=mindflow,dc=com"
            SearchFilter    "uid=%u"
            RequireGroup    true
            <Group>
                    BaseDN          "ou=confluence-jira,ou=group,dc=mindflow,dc=com"
                    SearchFilter    "(cn=研发部)"
                    MemberAttribute uniqueMember
            </Group>
    </Authorization>

  setup-certs.sh: |-
    #!/bin/bash
    EASY_RSA_LOC="/etc/openvpn/certs"
    cd $EASY_RSA_LOC
    SERVER_CERT="${EASY_RSA_LOC}/pki/issued/server.crt"
    if [ -e "$SERVER_CERT" ]
    then
      echo "found existing certs - reusing"
      {{- if .Values.openvpn.useCrl }}
      if [ ! -e ${EASY_RSA_LOC}/crl.pem ]
      then
        echo "generating missed crl file"
        ./easyrsa gen-crl
        cp ${EASY_RSA_LOC}/pki/crl.pem ${EASY_RSA_LOC}/crl.pem
        chmod 644 ${EASY_RSA_LOC}/crl.pem
      fi
      {{- end }}
      {{- if .Values.openvpn.taKey }}
        if [ ! -e ${EASY_RSA_LOC}/pki/ta.key ]
        then
          echo "generating missed ta.key"
          openvpn --genkey --secret ${EASY_RSA_LOC}/pki/ta.key
        fi
      {{- end }}
    else
      cp -R /usr/share/easy-rsa/* $EASY_RSA_LOC
      ./easyrsa init-pki
      echo "ca\n" | ./easyrsa build-ca nopass
      ./easyrsa build-server-full server nopass
      ./easyrsa gen-dh
      {{- if .Values.openvpn.useCrl }}
      ./easyrsa gen-crl
      cp ${EASY_RSA_LOC}/pki/crl.pem ${EASY_RSA_LOC}/crl.pem # Note: the pki/ directory is inaccessible after openvpn drops privileges, so we cp crl.pem to ${EASY_RSA_LOC} to allow CRL updates without a restart
      chmod 644 ${EASY_RSA_LOC}/crl.pem
      {{- end }}
      {{- if .Values.openvpn.taKey }}
      openvpn --genkey --secret ${EASY_RSA_LOC}/pki/ta.key
      {{- end }}
    fi


  newClientCert.sh: |-
    #!/bin/bash
    EASY_RSA_LOC="/etc/openvpn/certs"
    cd $EASY_RSA_LOC
    MY_IP_ADDR="$2"
    ./easyrsa build-client-full $1 nopass
    cat >${EASY_RSA_LOC}/pki/$1.ovpn <<EOF
    client
    nobind
    dev tun
    {{- if eq .Values.service.type "NodePort" }}
    remote ${MY_IP_ADDR} {{ .Values.service.nodePort }} {{ .Values.openvpn.OVPN_PROTO }}
    {{- else }}
    remote ${MY_IP_ADDR} {{ .Values.service.externalPort }} {{ .Values.openvpn.OVPN_PROTO }}
    {{- end }}
    {{ if .Values.openvpn.cipher }}
    cipher {{ .Values.openvpn.cipher }}
    {{- end }}
    {{ if .Values.openvpn.redirectGateway }}
    redirect-gateway def1
    {{- end }}
    {{ if .Values.openvpn.clientConf }}
    {{ indent 6 .Values.openvpn.clientConf }}
    {{- end }}
    <key>
    `cat ${EASY_RSA_LOC}/pki/private/$1.key`
    </key>
    <cert>
    `cat ${EASY_RSA_LOC}/pki/issued/$1.crt`
    </cert>
    <ca>
    `cat ${EASY_RSA_LOC}/pki/ca.crt`
    </ca>
    {{- if .Values.openvpn.taKey }}
    <tls-auth>
    `cat ${EASY_RSA_LOC}/pki/ta.key`
    </tls-auth>
    key-direction 1
    {{- end }}
    EOF
    cat pki/$1.ovpn

  revokeClientCert.sh: |-
    #!/bin/bash
    EASY_RSA_LOC="/etc/openvpn/certs"
    cd $EASY_RSA_LOC
    ./easyrsa revoke $1
    ./easyrsa gen-crl
    cp ${EASY_RSA_LOC}/pki/crl.pem ${EASY_RSA_LOC}
    chmod 644 ${EASY_RSA_LOC}/crl.pem

  configure.sh: |-
    #!/bin/sh

    cidr2mask() {
       # Number of args to shift, 255..255, first non-255 byte, zeroes
       set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
       [ $1 -gt 1 ] && shift "$1" || shift
       echo ${1-0}.${2-0}.${3-0}.${4-0}
    }

    cidr2net() {
        local i ip mask netOctets octets
        ip="${1%/*}"
        mask="${1#*/}"
        octets=$(echo "$ip" | tr '.' '\n')

        for octet in $octets; do
            i=$((i+1))
            if [ $i -le $(( mask / 8)) ]; then
                netOctets="$netOctets.$octet"
            elif [ $i -eq  $(( mask / 8 +1 )) ]; then
                netOctets="$netOctets.$((((octet / ((256 / ((2**((mask % 8)))))))) * ((256 / ((2**((mask % 8))))))))"
            else
                netOctets="$netOctets.0"
            fi
        done

        echo ${netOctets#.}
    }

    /etc/openvpn/setup/setup-certs.sh
    {{ if .Values.openvpn.istio.enabled }}
    iptables -t nat -A PREROUTING -s {{ .Values.openvpn.OVPN_NETWORK }}/{{ .Values.openvpn.OVPN_SUBNET }} -i tun0 -p tcp -j REDIRECT --to-ports {{ .Values.openvpn.istio.proxy.port }}
    {{ end }}

    {{ range .Values.openvpn.iptablesExtra }}
    iptables {{ . }}
    {{ end }}

    iptables -t nat -A POSTROUTING -s {{ .Values.openvpn.OVPN_NETWORK }}/{{ .Values.openvpn.OVPN_SUBNET }} -o eth0 -j MASQUERADE
    mkdir -p /dev/net
    if [ ! -c /dev/net/tun ]; then
        mknod /dev/net/tun c 10 200
    fi

    if [ "$DEBUG" == "1" ]; then
        echo ========== ${OVPN_CONFIG} ==========
        cat "${OVPN_CONFIG}"
        echo ====================================
    fi

    intAndIP="$(ip route get 8.8.8.8 | awk '/8.8.8.8/ {print $5 "-" $7}')"
    int="${intAndIP%-*}"
    ip="${intAndIP#*-}"
    cidr="$(ip addr show dev "$int" | awk -vip="$ip" '($2 ~ ip) {print $2}')"
    NETWORK="$(cidr2net $cidr)"
    NETMASK="$(cidr2mask ${cidr#*/})"
    DNS=$(cat /etc/resolv.conf | grep -v '^#' | grep nameserver | awk '{print $2}')
    SEARCH=$(cat /etc/resolv.conf | grep -v '^#' | grep search | awk '{$1=""; print $0}')
    FORMATTED_SEARCH=""
    for DOMAIN in $SEARCH; do
      FORMATTED_SEARCH="${FORMATTED_SEARCH}push \"dhcp-option DOMAIN-SEARCH ${DOMAIN}\"\n"
    done
    cp -f /etc/openvpn/setup/openvpn.conf /etc/openvpn/
    sed 's|OVPN_K8S_SEARCH|'"${FORMATTED_SEARCH}"'|' -i /etc/openvpn/openvpn.conf
    sed 's|OVPN_K8S_DNS|'"${DNS}"'|' -i /etc/openvpn/openvpn.conf
    sed 's|NETWORK|'"${NETWORK}"'|' -i /etc/openvpn/openvpn.conf
    sed 's|NETMASK|'"${NETMASK}"'|' -i /etc/openvpn/openvpn.conf
    apk add openvpn-auth-ldap --update-cache --repository http://dl-4.alpinelinux.org/alpine/edge/main/
    sysctl -w net.ipv4.ip_forward=1
    exec openvpn --config /etc/openvpn/openvpn.conf
  openvpn.conf: |-
    server {{ .Values.openvpn.OVPN_NETWORK }} {{ .Values.openvpn.OVPN_SUBNET }}
    verb 3
    {{ if .Values.openvpn.useCrl }}
    crl-verify /etc/openvpn/certs/crl.pem
    {{ end }}
    key /etc/openvpn/certs/pki/private/server.key
    ca /etc/openvpn/certs/pki/ca.crt
    cert /etc/openvpn/certs/pki/issued/server.crt
    dh /etc/openvpn/certs/pki/dh.pem
    {{ if .Values.openvpn.taKey }}
    tls-auth /etc/openvpn/certs/pki/ta.key 0
    {{ end }}

    {{ if .Values.openvpn.cipher }}
    cipher {{ .Values.openvpn.cipher }}
    {{ end }}
    key-direction 0
    keepalive 10 60
    persist-key
    persist-tun

    proto {{ .Values.openvpn.OVPN_PROTO }}
    port  {{ .Values.service.internalPort }}
    dev tun0
    status /tmp/openvpn-status.log

    user nobody
    group nogroup

    {{ if .Values.openvpn.ccd.enabled }}
    client-config-dir /etc/openvpn/ccd
    {{ end }}

    {{ if .Values.openvpn.DEFAULT_ROUTE_ENABLED }}
    push "route NETWORK NETMASK"
    {{ end }}
    {{ if and (.Values.openvpn.OVPN_K8S_POD_NETWORK) (.Values.openvpn.OVPN_K8S_POD_SUBNET) }}
    push "route {{ .Values.openvpn.OVPN_K8S_POD_NETWORK }} {{ .Values.openvpn.OVPN_K8S_POD_SUBNET }}"
    {{ end }}
    {{ if and (.Values.openvpn.OVPN_K8S_SVC_NETWORK) (.Values.openvpn.OVPN_K8S_SVC_SUBNET) }}
    push "route {{ .Values.openvpn.OVPN_K8S_SVC_NETWORK }} {{ .Values.openvpn.OVPN_K8S_SVC_SUBNET }}"
    {{ end }}

    {{ if .Values.openvpn.dhcpOptionDomain }}
    OVPN_K8S_SEARCH
    {{ end }}
    push "dhcp-option DNS OVPN_K8S_DNS"

    plugin /usr/lib/openvpn/plugins/openvpn-auth-ldap.so "/etc/openvpn/setup/auth-ldap.conf uid=%u"

    client-cert-not-required
    
    {{- if .Values.openvpn.serverConf }}
    {{ indent 6 .Values.openvpn.serverConf }}
    {{- end -}}

3.3 修改deployment

cd /root/helm/charts/stable/openvpn/templates
vi openvpn-deployment.yaml

3.3.1 修改主机权限

securityContext内加入privileged,加入后的效果如下

        ...
        securityContext:
          capabilities:
            add:
              - NET_ADMIN
          privileged: true
        ...

4 启动openvpn服务

  1. 输入下方命令进行启动

    cd /root/helm/charts/stable
    helm install openvpn openvpn/ -n ops
    
  2. 查看运行日志

    kubectl logs -f $(kubectl get pod -n ops | grep openvpn | awk '{print $1}') -n ops
    

5 ovpn连接文件

5.1 创建ovpn

  1. 输入下方命令进入pod

    kubectl exec -it $(kubectl get pod -n ops | grep openvpn | awk '{print $1}') sh -n ops
    
  2. 进入后输入以下命令会创建ovpn文件

    cd /etc/openvpn/setup/
    sh newClientCert.sh client名 连接的IP
    
  3. 下载ovpn文件

    cd /etc/openvpn/certs/pki
    sz client名.ovpn
    

5.2 修改ovpn

  1. redirect-gateway def1删除(这行的意思是所有的流量都走vpn,如果有需要可以不删除)

  2. <key><cert>标签删除,注意<ca>千万不要删除

  3. 修改端口并加入ldap的配置使用用户名密码

    ns-cert-type server
    auth-user-pass
    

最终ovpn文件类似如下:

client
nobind
dev tun
remote 192.168.101.202 30803 tcp
ns-cert-type server
auth-user-pass


<ca>
-----BEGIN CERTIFICATE-----
很长一串的秘钥
-----END CERTIFICATE-----
</ca>

导入openvpn-client连接即可