使用 Apache2 WebDAV 阻止文件覆盖

问题描述

我正在设置一个内部服务器,允许使用 HTTP 将匿名文件上传到特定目录。请注意,我试图避免实现基于 Python、PHP 等的东西,以保持此设置尽可能简单,因为我可能不是将来最终支持此系统的人。

我有一个使用 Apache2 的 WebDAV 模块的基本设置,但我也想阻止覆盖当前存在的任何文件。 WebDAV 有扩展吗?

这是我当前的配置脚本:

### Base HTML Directory
DIR_BASE=/var/www/html
mkdir -p $DIR_BASE
# Ownership
find $DIR_BASE -type f -exec chown root:apache {} \;
find $DIR_BASE -type d -exec chown root:apache {} \;
# Permission
find $DIR_BASE -type f -exec chmod 0644 {} \;
find $DIR_BASE -type d -exec chmod 0755 {} \;
# SELinux - Allow Apache to serve contents
chcon -t httpd_sys_content_t $DIR_BASE -Rv
### Upload HTML Directory
DIR_UPLOAD=/var/www/html/uploads
mkdir -p $DIR_UPLOAD
# Ownership
find $DIR_UPLOAD -type f -exec chown root:apache {} \;
find $DIR_UPLOAD -type d -exec chown root:apache {} \;
# Permission
find $DIR_UPLOAD -type f -exec chmod 0644 {} \;
find $DIR_UPLOAD -type d -exec chmod 0775 {} \;
# SELinux - Allow Apache to write to directory
chcon -u system_u -t httpd_sys_rw_content_t $DIR_UPLOAD -Rv
### Web Service
# Upload Section
#  <Directory "/var/www/html/uploads">
#    Options None # Don't allow any secondary features,such as listing the files
#    AllowOverride None # Don't allow overrides from other configuration files
#    Allow from all # Anonymous Access
#    Require all granted # Anonymous Access
#  </Directory>
#  <Location /uploads>
#    Dav On # WebDAV for file upload functionality
#    <LimitExcept PUT> # Limit to file upload only
#      Order Allow,Deny # Anonymous Access
#      Allow from all # Anonymous Access
#    </LimitExcept>
#  </Location>
cat > /etc/httpd/conf.d/uploads.conf << _EOF
Alias /uploads "/var/www/html/uploads"
  <Directory "/var/www/html/uploads">
    Options None
    AllowOverride None
    Allow from all
    Require all granted
  </Directory>
  <Location /uploads>
    Dav On
    <LimitExcept PUT>
      Order Allow,Deny
      Allow from all
    </LimitExcept>
  </Location>
_EOF
restorecon -vF /etc/httpd/conf.d/uploads.conf
systemctl enable httpd
systemctl restart httpd
### Firewall
firewall-cmd --add-service=http --permanent
firewall-cmd --reload

解决方法

我使用 inotify-tools 包找到了我的解决方案。我最初计划使用一个简单的 cron 作业进行批处理,但使用该包我可以执行按需单文件处理。鉴于我希望收到的文件量相对较少,这应该能很好地满足我的需求。

我的原始脚本中的所有内容都相同,但我添加了以下内容:

### File Processing
PROCESSED=/data/processed
mkdir -p $PROCESSED
# Ownership
find $PROCESSED -type f -exec chown root:wheel {} \;
find $PROCESSED -type d -exec chown root:wheel {} \;
# Permission
find $PROCESSED -type f -exec chmod 0644 {} \;
find $PROCESSED -type d -exec chmod 0755 {} \;
# Bash Script
mkdir -p /root/scripts
cat > /root/scripts/uploadprocesser.sh << '_EOF'
#!/bin/bash

SOURCE=/var/www/html/uploads
PROCESSED=/data/processed

inotifywait -m -e create -e moved_to --format "%f" $SOURCE \
    | while read FILENAME
        do
            if [[ $FILENAME != ".davfs.tmp"* ]]; then
                echo "Detected $FILENAME,moving"
                mv --backup=numbered "$SOURCE/$FILENAME" "$PROCESSED/$FILENAME"
            fi
        done
_EOF
chmod +x /root/scripts/uploadprocesser.sh
# Systemd Service
cat > /etc/systemd/system/uploadprocesser.service << _EOF
[Unit]
Description=File Upload Processing Service
After=httpd.service
[Service]
Type=simple
Restart=always
RestartSec=1
User=root
ExecStart=/bin/bash /root/scripts/uploadprocesser.sh

[Install]
WantedBy=multi-user.target
_EOF
systemctl daemon-reload
systemctl enable uploadprocesser
systemctl restart uploadprocesser

而且由于 mv 包含一个内置的文件轮换系统,它不需要我阻止覆盖。 PMF 的评论让我想到了这些,所以谢谢你!

[root@localhost ~]# ls /var/www/html/uploads/
lost+found

[root@localhost ~]# ls /data/processed/
test1  test1.~1~  test1.~2~  test1.~3~  test1.~4~  test1.~5~