package cc.mrbird.febs.firewall.nginx; import cc.mrbird.febs.firewall.entity.FirewallSite; import cc.mrbird.febs.firewall.mapper.FirewallCountryRuleMapper; import cc.mrbird.febs.firewall.mapper.FirewallSiteMapper; import cn.hutool.core.io.FileUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.List; /** * Nginx 国家黑名单配置文件生成器 *

* 默认放行所有国家,仅拦截配置中选中的国家(黑名单模式)。 *

* 输出文件: /etc/nginx/conf.d/firewall_country_{siteId}.conf *

* 不直接执行 reload,仅负责文件生成。 * reload 由 NginxReloadTask 消费 Redis 队列后执行,防止误操作。 * * @author auto-generated * @date 2026-07-31 */ @Slf4j @Component @RequiredArgsConstructor public class NginxConfigGenerator { private final FirewallCountryRuleMapper mapper; private final FirewallSiteMapper siteMapper; /** Nginx 配置目录 */ private static final String NGINX_CONF_DIR = "/etc/nginx/conf.d/"; /** 配置文件前缀 */ private static final String CONF_PREFIX = "firewall_country_"; /** * 生成 Nginx 国家黑名单 map 配置 *

     * map $geoip_country_code $allow_country {
     *     default 1;
     *     JP 0;
     *     US 0;
     * }
     * 
* default 1 表示默认放行,列表中国家设为 0 表示拦截。 * Nginx 中判断: if ($allow_country_1 = 0) { return 403; } * * @param siteId 站点ID */ public void generate(Long siteId) { // 查询站点配置路径 FirewallSite site = siteMapper.selectById(siteId); if (site == null) { log.warn("防火墙站点不存在: siteId={}", siteId); return; } List countries = mapper.selectEnableCountry(siteId); StringBuilder sb = new StringBuilder(); sb.append("# Firewall Country Block Map (Blacklist)\n"); sb.append("# Site: ").append(site.getSiteName()).append(" (").append(site.getDomain()).append(")\n"); sb.append("# Generated at: ").append(new java.util.Date()).append("\n\n"); sb.append("map $geoip_country_code $allow_country_").append(siteId).append(" {\n"); sb.append(" default 1;\n"); for (String c : countries) { sb.append(" ").append(c.toUpperCase()).append(" 0;\n"); } sb.append("}\n"); // 写入文件 String confFileName = site.getNginxConf(); if (confFileName == null || confFileName.isEmpty()) { confFileName = NGINX_CONF_DIR + CONF_PREFIX + siteId + ".conf"; } File confFile = new File(confFileName); try { FileUtil.writeString(sb.toString(), confFile, StandardCharsets.UTF_8); log.info("Nginx 黑名单配置已生成: {}, 拦截国家: {}", confFile.getAbsolutePath(), countries); } catch (Exception e) { log.error("Nginx 配置文件写入失败: path={}", confFile.getAbsolutePath(), e); throw new RuntimeException("Nginx 配置文件写入失败: " + e.getMessage(), e); } } }