NoPKT网络构建日志(一)

本系列日志主要记录NoPKT网络基础服务的搭建过程,以备后续维护时记忆查询。
本篇内容主要目的是记录RPKI相关服务的搭建。

MySQL数据库部署

数据库作为后续各种服务的建设基础,要充分考虑稳定性和备份,这里在建设初期将数据保护(数据持久性)优先于稳定性和性能考虑。因此在Home Lab内NUC部署服务并将数据目录通过NAS进行挂载。
Docker模式部署命令:

docker network create --subnet=<各关联服务的容器组网IP段> nopktbr
docker run --name=mysqldb \ 
   --mount type=bind,src=<主机挂载NAS路径(需存在的文件)>,dst=/etc/my.cnf \ 
   --mount type=bind,src=<主机挂载NAS路径(需存在的目录)>,dst=/var/lib/mysql \ 
   --network=bridge --ip <mysql服务容器IP> \ 
   -d container-registry.oracle.com/mysql/community-server:latest

启动之后可以查看容器日志找到root用户的临时密码,以下面命令连接:

mysql -h <mysql服务容器IP> -u root -p

如遇到主机没装mysql-client可通过下面命令安装(Debian环境为例)

apt install mysql-client

apt install default-mysql-client

连接上mysql后,进行root密码修改和创建DBA用户并授权远程连接权限:

ALTER USER 'root'@'localhost' IDENTIFIED BY '<新的root密码>';
CREATE USER '<新建DBA用户名>'@'%' IDENTIFIED WITH mysql_native_password BY '<DBA用户密码>';
GRANT ALL PRIVILEGES ON *.* TO '<DBA用户名>'@'%';

注:如此设置会在MySQL日志产生'mysql_native_password' is deprecated and will be removed警告,但实际当前最新版8.3.0仍可用,暂时不作处理

Keycloak部署

由于期望使用krill自建RPKI并实现可以多用户管理krill去自主创建ROA,并与网站用户管理统一起来,因此暂时考虑搭建Keycloak。
首先,在前面建设的MySQL服务上使用DBA创建数据库:

CREATE DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_general_ci;

需要注意的是,这里是使用utf8还是utf8mb4并不十分确定。按照keycloak官方说法 是不支持utf8mb4,后续如有结论再进行更新。这里先如此设置,并且在连接时不按支持utf8处理。
之后就是docker创建keycloak容器,此处采用portainer部署,故不再给出命令了,可以根据需要自行拼接命令。

  1. 容器名称:keycloak

  2. 镜像:quay.io/keycloak/keycloak:latest

  3. 覆写镜像命令:start --proxy edge
    这里添加代理模式是考虑前面要加Nginx反代通过域名暴露服务,不加是否可以还未确认。这里因为外面套有隧道保障安全,故在反代和服务间采用HTTP连接,所以设置为edge模式。

  4. 文件映射:/opt/keycloak/server.pem映射到主机证书文件路径,/opt/keycloak/server.key映射到主机密钥文件。实际上因为前面有反代,这里并不需要HTTPS,只是貌似keycloak没法禁掉HTTPS故保留证书配置,证书的DN无所谓。

  5. 网络:选择前面MySQL同样的bridge网络,并指定其IP

  6. 设置以下环境变量值:

    环境变量名 环境变量值
    KEYCLOAK_ADMIN <keycloak管理员账号>
    KEYCLOAK_ADMIN_PASSWORD <keycloak管理员口令>
    KC_HEALTH_ENABLED true
    KC_METRICS_ENABLED true
    KC_DB mysql
    KC_DB_URL jdbc:mysql://<mysql服务容器的bridge网络地址>/keycloak
    KC_DB_USERNAME <DBA账号>
    KC_DB_PASSWORD <DBA口令>
    KC_HOSTNAME_URL <keycloak服务全路径,如https://login.host.com/>
    KC_HOSTNAME_ADMIN_URL <keycloak管理员全路径,如https://keycloak.host.com/>
    KC_HTTPS_CERTIFICATE_FILE /opt/keycloak/server.pem
    KC_HTTPS_CERTIFICATE_KEY_FILE /opt/keycloak/server.key
    KC_HTTP_ENABLED true
  7. 设置重启策略:按需求设置即可。

配置Keycloak前置反代

这里已经在公网机器上配置好了NginxProxyManager,并将CLoudflare的DNS配置为使用严格安全(Full strict)的DNS代理到这台NPM所在机器地址。
然后,在NPM上面添加前面设置的Keycloak的反代,域名为前面环境变量设置过的域名,后端协议设置为http、端口为8080、主机为Keycloak容器在bridge网络中的IP。
之后应该就可以通过Keycloak的URL进行访问了。

为Krill进行Keycloak初始配置

之后就可以在Keycloak上为Krill进行一些初始的配置了。主要是参考Krill官方文档,但不得不说Krill官方文档还是以Keycloak 12.0.4版本为依据来写的(我部署时Keycloak已经到23.0.4),并不是能很精确地对应上。所以,接下来的这些配置中也可能会存在一些问题,等遇到后会更新说明。

  1. 创建租户
    访问Keycloak的URL地址,点击在左侧的Administration Console进入管理员控制台,使用管理员的账户和口令登入。点击左侧导航栏顶部下拉菜单创建realm(类似tenant概念),为Krill创建组织(日后网络服务平台可以考虑和Krill共用realm,也可以分开,到时候再看了),创建时仅需要设置个名字即可创建,但是需要注意的是,这里名字在后续使用时会区分大小写,建议都小写避免不必要的麻烦。
  2. 创建Krill连接客户端
    在当前选择前面创建的realm情况下,点左侧导航栏的Clients并点击页面上的Create Clients,在创建页面上把Client ID设置为krill即可。点击Next在下面页面把Client authentication打开。再点击Next在页面上设置重要的几个URL,其中最主要的是把Valid redirect URIs设置为https://<将给Krill的域名>/auth/callbackhttps://<将给Krill的域名>/两条,其他的可以根据需要后续再配。
  3. 添加用户角色属性映射
    这一步的页面就跟Krill的文档不大一致了。点击左侧导航的Client scope,并点击页面的Create client scope。Name设置为role,Type考虑设置为Default,其它可以默认完成创建。之后出现的页面上选择Mappers页签,配置新映射,映射类型选择User Attribute。映射名称krill_role,User Attribute设置为role,Token Claim Name设置为role,进行保存。完成scope添加后记得回到krill这个Client的详情中的Client scope页签下把这个新scope添加进去。
  4. 创建Krill管理员用户
    Keycloak这边最后的配置是为Krill创建管理员用户。点左侧导航栏Users,然后选择添加用户。
    设置用户名、邮箱、邮箱已验证、姓名,保存后再到用户的Credentials页签下设置密码(按需要可以把临时密码选项去掉),在Attributes页签添加一条role属性的值为admin。

至此,完成Keycloak这边的初始配置。

Krill部署

同样这边Krill也选择Docker部署模式,便于携带迁移。同样采用Portainer部署,首先创建好krill的数据卷以供挂载进行数据持久化,依旧是挂载NAS目录。
部署设置为:卷宗挂载/var/krill/data到刚创建的数据卷、/var/krill/data/repo/rsync到主机的/tmp/krill_rsync。

  1. 容器名称:krill
  2. 镜像:nlnetlabs/krill:latest
  3. 文件映射:/var/krill/data挂载到刚创建的数据卷,/var/krill/data/repo/rsync绑定到主机/tmp/krill_rsync
  4. 网络:选择前面MySQL、Keycloak同样的bridge网络,并指定其IP
  5. 设置以下环境变量值:
    环境变量名 环境变量值
    KRILL_LOG_LEVEL debug
    KRILL_FQDN <krill服务的域名>
    KRILL_ADMIN_TOKEN <krill管理员token>
    TZ Asia/Shanghai

然后完成部署。
然后修改Krill的配置文件,到前面挂载的数据卷中,修改krill.conf文件,添加以下Keycloak的OIDC配置:

service_uri = "https://<krill服务域名>/"
auth_type = "openid-connect"

[auth_openidconnect]
issuer_url = "https://<keycloak服务域名>/realms/<为krill创建的租户名>"
client_id = "krill"
client_secret = "<krill客户端连接密钥>"

其中,krill客户端连接密钥在Keycloak的Clients页面中查看krill的详情,并在Credentials页签下可以拿到。
修改完成后重启容器即可。

Krill反代设置

这里类似的在NPM上为Krill域名配置反代。但需要注意的是,一是Krill服务端口是3000且协议是HTTPS,二是因为Keycloak认证信息体积大,需要在高级配置中添加以下两条(否则存在可能使用Keycloak认证完成跳转回Krill时出现500错误):

proxy_buffer_size   128k;
proxy_buffers   4 256k;

配置好后访问Krill服务域名,正常连接并跳转到Keycloak使用Krill管理员进行认证登录,正常情况下应该能进入Krill的欢迎页面。

RPKI的CA配置

首先在进入欢迎页后创建CA句柄,以用来和父CA交互。起个名称即可。
接下来配置步骤主要参考nlnetlabs的这篇博客
如果之前在RIPE使用hosted CA的需要先将其注销(revoke)掉,其中配置的ROA均会丢失,因此做好备份记录。
然后在RIPE的RPKI Dashboard上选择创建Delegated CA。回到Krill上在父级CA页签上选择添加额外的父级CA,将子CA请求XML下载,并上传回RIPE页面上显示的下一步中。然后在RIPE页面上下载父CA应答给Krill上传。然后给其取个名字并确认。之后等待在Krill父CA页面上正常显示父CA相关信息即可。
然后在Krill上创建新数据库,这个过程和前面添加父CA可以说完全一样,就不再赘述了。
等待数据库也接入完成后,就可以愉快地添加ROA了!