使用Casdoor+OAuth-Proxy保护公网网页应用

2022-02-15
4 min read

前言

前段时间把 Homelab 从矿渣更换为 HPE ProLiant MicroServer Gen10 Plus,不得不说企业级的产品还是比矿渣用起来会舒服很多。目前在 Gen10 Plus 上安装了 ESXi 作为虚拟化环境,跑着 DSM 和 OpenWRT ,开了一个虚拟机专门跑 Docker,同时也跑着我的开发环境。

家里的网络是带公网 IP 的,但是把网页应用直接暴露到公网会有各种各样的安全问题,因此之前一直在找方法保护暴露到公网上的应用。一开始是打算使用 APISIX 或者 Nginx 的AUTH方式来实现,但总感觉有点高射炮打蚊子的诡异感,因此一直没实施。前几天无意间接触到 OAuth-Proxy 这个应用,再加上自己也一直有参与一个 SSO 开源项目——Casdoor 的开发,于是便想着在 Homelab 上部署这套系统来保护暴露在公网上的网页应用

Casdoor 的部署与设置

Casdoor 是一款支持 OAuth 2.0、OIDC 和 SAML 的 UI 优先集中式身份验证/单点登录 (SSO) 平台,可以使用 Docker 或直接使用源码运行,安装步骤可见:安装文档

在安装完 Casdoor 后,使用初始账户密码:admin 123即可进入管理后台。

Casdoor登陆页面

在登陆 Casdoor 后我们可以添加一些提供商(下称 idp ),方便我们进行登录。如下图我已经添加了四个 idp :

Casdoor idp

Casdoor 支持的三方登录以及配置流程可以参考官方文档。在完成 idp 的添加后我们进入用户选项栏,我们可以选择添加一个用户或者就使用当前的 admin 账号,点击编辑按钮,进行三方登录账号的绑定,如下图我已完成所有账户的绑定:

Casdoor账户绑定

完成用户绑定后,前往应用选项栏,添加一个应用给 OAuth-Proxy 进行使用,目前我们不需要在这里设置过多东西,只需要在提供商部分把我们刚刚添加的 idp 添加上去:

应用IDP设置

然后我们可以把页面里显示的客户端ID客户端密钥记录下来,后面会使用到.记录相关信息

另外,个人建议把开启密码登录、启用注册关闭,只使用 idp 进行登录,进一步提高安全性:

image-20220215182421065

至此Casdoor的相关设置就基本结束。

OAuth-Proxy 部署及设置

OAuth-Proxy 的安装有几种方法,我这里是采用了最简单的预编译好的二进制文件。把下载好的可执行文件放到Homelab 中并设置好相关执行权限后,创建一个配置文件,可以根据示例配置文件进行修改。但由于普通的配置文件的 upstreams 功能不太直观,所以我使用的是 Alpha Configuration ,我使用的配置文件config.yml如下:

injectRequestHeaders:
- name: X-Forwarded-Groups
  values:
  - claim: groups
- name: X-Forwarded-User
  values:
  - claim: user
- name: X-Forwarded-Email
  values:
  - claim: email
- name: X-Forwarded-Preferred-Username
  values:
  - claim: preferred_username 
- name: X-Forwarded-Access-Token
  values:
  - claim: access_token
metricsServer:
  BindAddress: ""
  SecureBindAddress: ""
  TLS: null
providers:
- ADFSConfig: {}
  approvalPrompt: force
  azureConfig:
    tenant: common
  bitbucketConfig: {}
  clientID: 7cdxxx96cb6 #这里写刚刚Casdoor获取的客户端ID
  clientSecret: 0e6fxxxa36e7ec #这里写刚刚Casdoor获取的客户端m
  githubConfig: {}
  gitlabConfig: {}
  googleConfig: {}
  id: oidc=c58c570b63c9bdbfe00c
  keycloakConfig: {}
  loginGovConfig: {}
  oidcConfig:
    emailClaim: name
    groupsClaim: groups
    insecureSkipNonce: true
    issuerURL: https://door.example.in #Casdoor的部署地址,需要外网可以访问
    userIDClaim: name
  provider: oidc
server:
  BindAddress: "" #如果不用ssl,这里直接写0.0.0.0:端口号
  SecureBindAddress: :7443 #OAuth-Proxy的ssl端口号
  TLS:
    Cert:
      fromFile: /path/to/cert/example.pem #证书文件
    Key:
      fromFile: /path/to/cert/example.key #证书私钥
upstreamConfig: #这后面的部分就是目前我要保护的一些内网应用
  upstreams:
  - flushInterval: 1s
    id: dsm
    passHostHeader: true
    path: ^/dsm/(.*)$
    rewriteTarget: /$1
    proxyWebSockets: true
    uri: http://192.168.2.234:5000
    insecureSkipTLSVerify: true
  - id: emby
    path: ^/emby/(.*)$
    rewriteTarget: /$1
    uri: http://192.168.2.235:8096
  - id: pt
    path: ^/pt/(.*)$
    rewriteTarget: /transmission/web/$1
    uri: http://192.168.2.234:9091
  - id: esxi
    path: ^/esxi/(.*)$
    rewriteTarget: /ui/$1
    uri: https://192.168.2.135
    insecureSkipTLSVerify: true
  - id : esxisdk
    path: ^/sdk/(.*)$
    rewriteTarget: /sdk/$1
    uri: https://192.168.2.135
    insecureSkipTLSVerify: true
  - id: esxiscreen
    path: ^/screen(.*)$
    rewriteTarget: /screen$1
    uri: https://192.168.2.135
    insecureSkipTLSVerify: true
  - id: esxiws
    path: ^/ticket/(.*)$
    rewriteTarget: /ticket/$1
    insecureSkipTLSVerify: true
    uri: https://192.168.2.135

还有一些配置是 Alpha Configuration 无法配置的,因此还要一个普通的配置文件setting.cfg:

email_domains = [
    "*"
]
cookie_secret = "uq-aoO1wq4VVTvkshcNVmD6adSsuE="
cookie_secure = false

上面这个cookie_secret可以通过以下命令生成:

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1 | base64

完成上面的设置之后,运行:

./oauth2-proxy  --config setting.cfg  --alpha-config config.yml

然后就可以打开设置的地址,访问相关资源,比如我访问我设置的 emby ,会首先显示 OAuth-Proxy 的认证页面:

image-20220215213522390

点击按钮,就会跳转到 Casdoor 的认证页面:

image-20220215213612224

选择方便的方式进行登录,然后就可以看到 Emby 页面了:

image-20220215213759256

存在的问题

如果只打算反代一个网站,基本没有什么问题。如果像我这样希望用一个端口根据不同的路径访问,首先要设置pathrewriteTarget,大部分网站设置好这个就ok了,但是像 ESXi 管理页面这种比较麻烦,因为他不会根据当前 uri 来进行识别所有资源地址,因此可以看到配置文件我 ESXi 要反代很多个path,但是emby这种支持比较好,只设置根目录的转发,其他也能很好转发。因此如果应用不多,可以多开几个 OAuth-Proxy,每个 OAuth-Proxy 对应一个端口和应用。

还有一个问题是OpenWRT的网页始终无法通过反代打开,原因还待研究。