前言 除了已封装好的镜像为付费内容,其他内容为免费。
一、背景
最近集团年底前要求下架所有centos,系统不定期可能更换,还是容器方便。网上一大堆的宝塔方案,太重,不合适。
支付系统,安全第一(含底层操作系统),还是容器方便 ^_-
二、思路
三、开刀
3.1打镜像
建议官方购买原代码
3.2容器非root运行
3.2.1方案一
cat <<EOF > Dockerfile
# support not root
ENV NON_ROOT_USER=wwj
ENV NON_ROOT_GID="103" \\
NON_ROOT_UID="1003" \\
NON_ROOT_WORK_DIR=/opt/local/\${NON_ROOT_USER} \\
NON_ROOT_HOME_DIR=/home/\${NON_ROOT_USER}
RUN groupadd -g 65532 nonroot && useradd -m -s \${NON_ROOT_HOME_DIR} -u 65532 \${NON_ROOT_USER} -g nonroot
#Add permission to non-root user
RUN chmod -R g+wx /usr/local/openresty/nginx/logs/ && \\
mkdir -p /opt/local && \\
chmod -R g+wx /opt/local/ && \\
chown -R \${NON_ROOT_GID}:\${NON_ROOT_UID} /opt/local/
## 注意 ,避免文件引用导致镜像大。放在在copy操作后(这里/usr/src/rainbow-pay 是上面的解压文件,如放COPY前,镜像会变大)
RUN chmod -R g+wx /usr/local/openresty /usr/src/rainbow-pay && \
chown -R \${NON_ROOT_USER} /usr/local/openresty /usr/src/rainbow-pay && \
chmod 777 /run /dev/stdout && \
chmod -R 777 /var/run/openresty
# 避免root用户运行。或者用entrypoint.sh+gosu实现(登录后是root,运行是非root) !!!!重点是这里
USER \${NON_ROOT_USER}
EOF
3.2.2方案二
cat <<EOF > Dockerfile
# support not root
ENV NON_ROOT_USER=wwj
ENV NON_ROOT_GID="103" \\
NON_ROOT_UID="1003" \\
NON_ROOT_WORK_DIR=/opt/local/\${NON_ROOT_USER} \\
NON_ROOT_HOME_DIR=/home/\${NON_ROOT_USER}
RUN groupadd -g 65532 nonroot && useradd -m -s \${NON_ROOT_HOME_DIR} -u 65532 \${NON_ROOT_USER} -g nonroot
# support /usr/local/bin/gosu command,配合entrypoint.sh里的exec /usr/local/bin/gosu使用
ENV GOSU_VERSION 1.17
RUN set -eux; \\
\\
apk add --no-cache --virtual .gosu-deps \\
ca-certificates \\
dpkg \\
gnupg \\
; \\
\\
dpkgArch="\$(dpkg --print-architecture | awk -F- '{ print \$NF }')"; \\
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/\$GOSU_VERSION/gosu-\$dpkgArch"; \\
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/\$GOSU_VERSION/gosu-\$dpkgArch.asc"; \\
# verify the signature
export GNUPGHOME="\$(mktemp -d)"; \\
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \\
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \\
command -v gpgconf && gpgconf --kill all || :; \\
rm -rf "\$GNUPGHOME" /usr/local/bin/gosu.asc; \\
\\
# clean up fetch dependencies
apk del --no-network .gosu-deps; \\
\\
chmod +x /usr/local/bin/gosu; \\
# verify that the binary works
gosu --version; \\
gosu nobody true
#RUN chmod +x /entrypoint.sh
#ENTRYPOINT [ "/entrypoint.sh" ]
# 建议方式,不需要上面的 chmod +x
ENTRYPOINT ["sh", "/entrypoint.sh"]
EOF
## entrypoint.sh
cat <<EOF > entrypoint.sh
#!/bin/bash
# terminate on errors 如果出现命令执行失败,那么就应该退出脚本不继续往下执行,避免失败对后续有影响。可以避免操作失败还继续往下执行的问题
set -e
# set file Permission
# 获取主机用户id
#USER_ID=\${LOCAL_USER_ID:-5555}
## 给主机用户授权制定的非绑定挂载目录
#chown -R \$USER_ID /usr/src/rainbow-pay /usr/local/openresty/nginx/logs/ /usr/local/openresty /usr/bin /etc/supervisor /run /dev /usr/local/openresty/nginx
#
## 创建和主机用户相同uid的用户,名为op
#useradd --shell /bin/bash -u \$USER_ID -o -c "" -m op
#usermod -a -G root op
#export HOME=/home/op
exec /usr/local/bin/gosu \${NON_ROOT_USER} "\$@" # !!!!重点是这里,gosu可以实现程序非root运行
#exec "\$@"
EOF
四、问题处理
4.1Permission denied
/usr/local/openresty/nginx/logs/error.log" failed (13: Permission denied)
解决方案: 检查docker-compose挂载的logs目录权限 chmod 755 -R logs
4.2fpm没启动
fpm没启动!
NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
解决方案:fpm-pool.conf 指定user+group
4.3改不了admin密码
4.3.1排查:
-
初始表+admin默认密码已完成
-
密码改完没反映
-
新增不了商户
-
数据库直接改密码,新密码能登录
4.3.2思路:
-
容器启动权限问题?
-
还原容器最大权限root启动 --> 问题依旧
-
-
目前问题?
-
涉及目录都设置777 --> 问题依旧
-
-
找资料debug nginx + php日志 --> 无解
-
打印nginx内置变量 --> 无解
-
php源码调试 --> 解决
五、切入点
观察修改密码界面url
https://xx.com/admin/set.php?mod=account
找到源码
/admin/set.php
,includes/functions.php
-
set.php-打印 HTTP_REFERER
[//]: # (204行打印array)
echo '<pre>';
print_r($_SERVER);
[//]: # (结果)
Array
(
[PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/openresty/luajit/bin:/usr/local/openresty/nginx/sbin:/usr/local/openresty/bin:/usr/local/openresty/openssl/bin
[HOSTNAME] => de8628c4e65b
[DB_USER] => raixx-pay
[WORDPRESS_SITE_URL] => http://localhost:8123
[FS_METHOD] => direct
[DB_HOST] => raninxx-db
[DB_PASSWORD] => ResxxsdjYd
[DB_NAME] => rainbow-pay
[NON_ROOT_USER] => xx
[NON_ROOT_GID] => 103
[NON_ROOT_UID] => 1003
[NON_ROOT_WORK_DIR] => /opt/local/xx
[NON_ROOT_HOME_DIR] => /home/xx
[HOME] => /
[SUPERVISOR_ENABLED] => 1
[SUPERVISOR_PROCESS_NAME] => php-fpm
[SUPERVISOR_GROUP_NAME] => php-fpm
[USER] => nobody
[HTTP_COOKIE] => admin_token=3f42J9JlfRLiP%2B2TTfS1kxxxSxVWRmvbpqYYfChZJKlQfwhbEYcOkIRsj%2F0AlDz28RsytVf4b7byatz0jZ; PHPSESSID=os7udc5fqaaodon46qqcsdfbnl; cf_clearance=GGNlfoPwd4sXJz9Kf4l9i5Lyi0obFqHFfrlWxA.QJrA-1700032904-0-1-7a7512ae.2a1a34f6.c9b678d6-0.2.1700032904
[HTTP_CDN_LOOP] => cloudflare
[HTTP_PRIORITY] => u=0, i
[HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.9
[HTTP_REFERER] => https://xx.com/admin/set.php?mod=account
[HTTP_SEC_FETCH_DEST] => document
[HTTP_SEC_FETCH_USER] => ?1
[HTTP_SEC_FETCH_MODE] => navigate
[HTTP_SEC_FETCH_SITE] => same-origin
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
[HTTP_CONTENT_TYPE] => application/x-www-form-urlencoded
[HTTP_ORIGIN] => https://xx.com
[HTTP_UPGRADE_INSECURE_REQUESTS] => 1
[HTTP_SEC_CH_UA_PLATFORM] => "Windows"
[HTTP_SEC_CH_UA_MOBILE] => ?0
[HTTP_SEC_CH_UA] => "Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"
[HTTP_CACHE_CONTROL] => no-cache
[HTTP_PRAGMA] => no-cache
[HTTP_CF_VISITOR] => {"scheme":"https"}
[HTTP_X_FORWARDED_PROTO] => https
[HTTP_CF_RAY] => 8265bFRA
[HTTP_ACCEPT_ENCODING] => gzip
[HTTP_CF_IPCOUNTRY] => CN
[HTTP_CF_CONNECTING_IP] => 39.xx.45.xx
[HTTP_CONTENT_LENGTH] => 79
[HTTP_HOST] => rainbow-pay
[HTTP_X_FORWARDED_FOR] => 172.70.247.85
[HTTP_CONNECTION] => close
[REDIRECT_STATUS] => 200
[SERVER_NAME] => _
[SERVER_PORT] => 80
[SERVER_ADDR] => 172.18.0.7
[REMOTE_PORT] => 37340
[REMOTE_ADDR] => 172.18.0.5
[SERVER_SOFTWARE] => nginx/1.21.4
[GATEWAY_INTERFACE] => CGI/1.1
[REQUEST_SCHEME] => http
[SERVER_PROTOCOL] => HTTP/1.1
[DOCUMENT_ROOT] => /usr/src/rxxw-pay
[DOCUMENT_URI] => /admin/set.php
[REQUEST_URI] => /admin/set.php?mod=account_n
[SCRIPT_NAME] => /admin/set.php
[CONTENT_LENGTH] => 79
[CONTENT_TYPE] => application/x-www-form-urlencoded
[REQUEST_METHOD] => POST
[QUERY_STRING] => mod=account_n
[PATH_TRANSLATED] => /usr/src/rainbow-pay
[PATH_INFO] =>
[SCRIPT_FILENAME] => /usr/src/rxxw-pay/admin/set.php
[FCGI_ROLE] => RESPONDER
[PHP_SELF] => /admin/set.php
[REQUEST_TIME_FLOAT] => 1700032918.2238
[REQUEST_TIME] => 1700032918
)
-
set.php-打印parse_url
[//]: # (204行打印array)
echo '<pre>';
print_r(parse_url($_SERVER['HTTP_REFERER']));
[//]: # (结果)
Array
(
[scheme] => https
[host] => pay.xx.com
[path] => /admin/set.php
[query] => mod=account
)