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 国家黑名单配置文件生成器
|
* <p>
|
* 默认放行所有国家,仅拦截配置中选中的国家(黑名单模式)。
|
* <p>
|
* 输出文件: /etc/nginx/conf.d/firewall_country_{siteId}.conf
|
* <p>
|
* 不直接执行 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 配置
|
* <pre>
|
* map $geoip_country_code $allow_country {
|
* default 1;
|
* JP 0;
|
* US 0;
|
* }
|
* </pre>
|
* 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<String> 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);
|
}
|
}
|
}
|