Skip to content

Commit 8eac75f

Browse files
authored
Merge pull request #196 from jason5ng32/dev
Security Updates
2 parents 7dadcaf + a702a6d commit 8eac75f

File tree

7 files changed

+71
-29
lines changed

7 files changed

+71
-29
lines changed

.env.example

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
PORT=11966
1+
BACKEND_PORT=18966
2+
FRONTEND_PORT=11966
23
BING_MAP_API_KEY=""
34
ALLOWED_DOMAINS=""
45
IPINFO_API_TOKEN=""
@@ -7,5 +8,6 @@ IPCHECKING_API_KEY=""
78
CLOUDFLARE_API=""
89
VITE_RECAPTCHA_SITE_KEY=""
910
RECAPTCHA_SECRET_KEY=""
10-
BLACKLIST_LOG_FILE_PATH=""
11-
RATE_LIMIT=""
11+
SECURITY_BLACKLIST_LOG_FILE_PATH=""
12+
SECURITY_RATE_LIMIT=""
13+
SECURITY_DELAY_AFTER=""

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ You can use the program without adding any environment variables, but if you wan
9999

100100
| Variable Name | Required | Default Value | Description |
101101
| --- | --- | --- | --- |
102-
| `PORT` | No | `18966` | The port on which the program runs |
102+
| `BACKEND_PORT` | No | `18966` | The running port of the backend part of the program |
103+
| `FRONTEND_PORT` | No | `11966` | The running port of the frontend part of the program |
104+
| `SECURITY_RATE_LIMIT` | No | `0` | Controls the number of requests an IP can make to the backend server every 60 minutes (set to 0 for no limit) |
105+
| `SECURITY_DELAY_AFTER` | No | `0` | Controls the first X requests from an IP every 20 minutes that are not subject to speed limits, and after X requests, the delay will increase |
106+
| `SECURITY_BLACKLIST_LOG_FILE_PATH` | No | `logs/blacklist-ip.log` | Path setting. Records the list of IPs that triggered the limit after SECURITY_RATE_LIMIT is enabled |
103107
| `BING_MAP_API_KEY` | No | `""` | API Key for Bing Maps, used to display the location of the IP on a map |
104108
| `ALLOWED_DOMAINS` | No | `""` | Allowed domains for access, separated by commas, used to prevent misuse of the backend API |
105109
| `IPCHECKING_API_KEY` | No | `""` | API Key for IPCheck.ing, used to obtain accurate IP geolocation information |
@@ -109,6 +113,8 @@ You can use the program without adding any environment variables, but if you wan
109113
| `VITE_RECAPTCHA_SITE_KEY` | No | `""` | Google reCAPTCHA's Site Key, used to display reCAPTCHA verification on the frontend |
110114
| `RECAPTCHA_SECRET_KEY` | No | `""` | Google reCAPTCHA's Secret Key, used to verify reCAPTCHA verification on the backend |
111115

116+
*Environment variables starting with `SECURITY_` are only valid when deploying using npm or Docker.*
117+
112118
### Using Environment Variables in a Node Environment
113119

114120
Create environment variables:
@@ -120,7 +126,8 @@ cp .env.example .env
120126
Modify `.env`, and for example, add the following:
121127

122128
```bash
123-
PORT=18966
129+
BACKEND_PORT=18966
130+
FRONTEND_PORT=11966
124131
BING_MAP_API_KEY="YOUR_KEY_HERE"
125132
ALLOWED_DOMAINS="example.com"
126133
IPCHECKING_API="YOUR_KEY_HERE"

README_FR.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,11 @@ Vous pouvez utiliser le programme sans ajouter de variables d'environnement, mai
9999

100100
| Nom de la variable | Requis | Valeur par défaut | Description |
101101
| --- | --- | --- | --- |
102-
| `PORT` | Non | `18966` | Le port sur lequel le programme s'exécute |
102+
| `BACKEND_PORT` | Non | `18966` | Le port d'exécution de la partie backend du programme |
103+
| `FRONTEND_PORT` | Non | `11966` | Le port d'exécution de la partie frontend du programme |
104+
| `SECURITY_RATE_LIMIT` | Non | `0` | Contrôle le nombre de requêtes qu'une adresse IP peut faire au serveur backend toutes les 60 minutes (réglé sur 0 pour aucune limite) |
105+
| `SECURITY_DELAY_AFTER` | Non | `0` | Contrôle les premières X requêtes d'une adresse IP toutes les 20 minutes qui ne sont pas soumises à des limites de vitesse, et après X requêtes, le délai augmentera |
106+
| `SECURITY_BLACKLIST_LOG_FILE_PATH` | Non | `logs/blacklist-ip.log` | Paramètre de chemin. Enregistre la liste des adresses IP qui ont déclenché la limite après que `SECURITY_RATE_LIMIT` soit activé |
103107
| `BING_MAP_API_KEY` | Non | `""` | Clé API pour Bing Maps, utilisée pour afficher l'emplacement de l'adresse IP sur une carte |
104108
| `ALLOWED_DOMAINS` | Non | `""` | Domaines autorisés pour l'accès, séparés par des virgules, utilisés pour empêcher une utilisation abusive de l'API backend |
105109
| `IPCHECKING_API_KEY` | Non | `""` | Clé API pour IPCheck.ing, utilisée pour obtenir des informations de géolocalisation précises sur l'adresse IP |
@@ -109,6 +113,8 @@ Vous pouvez utiliser le programme sans ajouter de variables d'environnement, mai
109113
| `VITE_RECAPTCHA_SITE_KEY` | Non | `""` | Clé de site reCAPTCHA de Google, utilisée pour afficher la vérification reCAPTCHA sur le frontend |
110114
| `RECAPTCHA_SECRET_KEY` | Non | `""` | Clé secrète reCAPTCHA de Google, utilisée pour vérifier la vérification reCAPTCHA sur le backend |
111115

116+
*Les variables d'environnement commençant par `SECURITY_` ne sont valides que lors du déploiement à l'aide de npm ou de Docker.*
117+
112118
### Utilisation des variables d'environnement dans un environnement Node
113119

114120
Créez les variables d'environnement :
@@ -120,7 +126,8 @@ cp .env.example .env
120126
Modifiez le fichier `.env`, et par exemple, ajoutez ce qui suit :
121127

122128
```bash
123-
PORT=18966
129+
BACKEND_PORT=18966
130+
FRONTEND_PORT=11966
124131
BING_MAP_API_KEY="YOUR_KEY_HERE"
125132
ALLOWED_DOMAINS="example.com"
126133
IPCHECKING_API="YOUR_KEY_HERE"

README_ZH.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ docker run -d -p 18966:18966 --name myip --restart always jason5ng32/myip:latest
101101

102102
| 变量名 | 是否必须 | 默认值 | 说明 |
103103
| --- | --- | --- | --- |
104-
| `PORT` || `18966` | 程序运行的端口 |
104+
| `BACKEND_PORT` || `18966` | 程序后端部分的运行端口 |
105+
| `FRONTEND_PORT` || `11966` | 程序前端部分的运行端口 |
106+
| `SECURITY_RATE_LIMIT` || `0` | 控制每 60 分钟一个 IP 可以对后端服务器请求的次数(设置为 0 则为不限制) |
107+
| `SECURITY_DELAY_AFTER` || `0` | 控制每 20 分钟一个 IP 的前 X 次请求不受速度限制,超过 X 次后会逐次增加延迟 |
108+
| `SECURITY_BLACKLIST_LOG_FILE_PATH` || `logs/blacklist-ip.log` | 路径设置。记录由 SECURITY_RATE_LIMIT 开启后,触发限制的 IP 列表 |
105109
| `BING_MAP_API_KEY` || `""` | Bing 地图的 API Key,用于展示 IP 所在地的地图 |
106110
| `ALLOWED_DOMAINS` || `""` | 允许访问的域名,用逗号分隔,用于防止后端 API 被滥用 |
107111
| `IPCHECKING_API_KEY` || `""` | IPCheck.ing 的 API Key,用于获取精准的 IP 归属地信息 |
@@ -111,6 +115,8 @@ docker run -d -p 18966:18966 --name myip --restart always jason5ng32/myip:latest
111115
| `VITE_RECAPTCHA_SITE_KEY` || `""` | Google reCAPTCHA 的 Site Key,用于在前端显示 reCAPTCHA 验证 |
112116
| `RECAPTCHA_SECRET_KEY` || `""` | Google reCAPTCHA 的 Secret Key,用于在后端验证 reCAPTCHA 验证 |
113117

118+
*`SECURITY_` 开头的环境变量仅在使用 npm 或 Docker 部署时有效。*
119+
114120
### 在 Node 环境里使用环境变量
115121

116122
创建环境变量:
@@ -122,7 +128,8 @@ cp .env.example .env
122128
修改 `.env` 里的内容,比如:
123129

124130
```bash
125-
PORT=18966
131+
BACKEND_PORT=18966
132+
FRONTEND_PORT=11966
126133
BING_MAP_API_KEY="YOUR_KEY_HERE"
127134
ALLOWED_DOMAINS="example.com"
128135
IPCHECKING_API="YOUR_KEY_HERE"

server.js

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import { slowDown } from 'express-slow-down'
1919
dotenv.config();
2020

2121
const app = express();
22-
const port = process.env.PORT || 11966;
23-
const blackListIPLogFilePath = process.env.BLACKLIST_LOG_FILE_PATH || '';
24-
const rateLimitSet = process.env.RATE_LIMIT || '60';
25-
const deleyAfter = process.env.DELAY_AFTER || '60';
22+
const backEndPort = process.env.BACKEND_PORT || 11966;
23+
const blackListIPLogFilePath = process.env.SECURITY_BLACKLIST_LOG_FILE_PATH || 'logs/blacklist-ip.log';
24+
const rateLimitSet = process.env.SECURITY_RATE_LIMIT || '0';
25+
const speedLimitSet = process.env.SECURITY_DELAY_AFTER || '0';
2626

2727
app.set('trust proxy', 1);
2828

@@ -42,6 +42,14 @@ function formatDate(timestamp) {
4242
function logLimitedIP(ip) {
4343
const logPath = path.join(__dirname, blackListIPLogFilePath);
4444

45+
// 如果 logs 目录不存在,则创建
46+
const logDir = path.dirname(logPath);
47+
if (!fs.existsSync(logDir)) {
48+
fs.mkdirSync(logDir, { recursive: true });
49+
console.log('Created log directory:', logDir);
50+
}
51+
52+
// 读取日志文件,更新 IP 计数,如果文件不存在则创建新的日志文件
4553
fs.readFile(logPath, 'utf8', (err, data) => {
4654
if (err && err.code !== 'ENOENT') {
4755
console.error('Error reading the log file:', err);
@@ -60,6 +68,7 @@ function logLimitedIP(ip) {
6068
if (currentIp === ip) {
6169
newCount = parseInt(count, 10) + 1;
6270
logExists = true;
71+
console.log(`IP ${ip} has been limited ${newCount} times`);
6372
return `${ip},${newCount},${timestamp}`; // Update count but keep the original timestamp
6473
}
6574
return line;
@@ -69,6 +78,7 @@ function logLimitedIP(ip) {
6978
if (!logExists) {
7079
const newLine = `${ip},${newCount},${formatDate(now)}`;
7180
updatedData += (updatedData ? '\n' : '') + newLine;
81+
console.log(`IP ${ip} has been limited for the first time`);
7282
}
7383

7484
fs.writeFile(logPath, updatedData, 'utf8', err => {
@@ -79,7 +89,7 @@ function logLimitedIP(ip) {
7989
});
8090
}
8191

82-
const apiLimiter = rateLimit({
92+
const rateLimiter = rateLimit({
8393
windowMs: 20 * 60 * 1000,
8494
max: parseInt(rateLimitSet, 10),
8595
message: 'Too Many Requests',
@@ -94,12 +104,22 @@ const apiLimiter = rateLimit({
94104

95105
const speedLimiter = slowDown({
96106
windowMs: 60 * 60 * 1000,
97-
delayAfter: parseInt(deleyAfter, 10),
107+
delayAfter: parseInt(speedLimitSet, 10),
98108
delayMs: (hits) => hits * 400,
99109
})
100110

101-
app.use('/api', apiLimiter);
102-
app.use('/api', speedLimiter);
111+
// 如果 rateLimitSet 为 0,则不启用限流
112+
if (parseInt(rateLimitSet, 10) !== 0) {
113+
app.use('/api', rateLimiter);
114+
console.log('Rate limiter is enabled');
115+
}
116+
117+
// 如果 deleyAfter 为 0,则不启用延迟
118+
if (parseInt(speedLimitSet, 10) !== 0) {
119+
app.use('/api', speedLimiter);
120+
console.log('Speed limiter is enabled');
121+
}
122+
103123

104124
// APIs
105125
app.get('/api/map', mapHandler);
@@ -110,8 +130,6 @@ app.get('/api/ipchecking', ipCheckingHandler);
110130
app.get('/api/ipsb', ipsbHandler);
111131
app.get('/api/cfradar', cfHander);
112132
app.get('/api/recaptcha', recaptchaHandler);
113-
114-
// DNS Resolver
115133
app.get('/api/dnsresolver', dnsResolver);
116134

117135
// 使用查询参数处理所有配置请求
@@ -124,6 +142,6 @@ app.use(express.static(path.join(__dirname, './dist')));
124142

125143

126144
// 启动服务器
127-
app.listen(port, () => {
128-
console.log(`Server running on http://localhost:${port}`);
145+
app.listen(backEndPort, () => {
146+
console.log(`Server running on http://localhost:${backEndPort}`);
129147
});

static-server.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ import { createProxyMiddleware } from 'http-proxy-middleware';
88
dotenv.config();
99

1010
const staticApp = express();
11-
const staticPort = 18966;
12-
const apiPort = process.env.PORT || 11966;
11+
const backEndPort = process.env.BACKEND_PORT || 11966;
12+
const frontEndPort = process.env.FRONTEND_PORT || 18966;
1313

1414
const __filename = fileURLToPath(import.meta.url);
1515
const __dirname = path.dirname(__filename);
1616

1717
// API 请求代理到后端服务
1818
staticApp.use('/api', createProxyMiddleware({
19-
target: `http://localhost:${apiPort}`,
19+
target: `http://localhost:${backEndPort}`,
2020
changeOrigin: true
2121
}));
2222

2323
// 设置静态文件目录
2424
staticApp.use(express.static(path.join(__dirname, './dist')));
2525

2626
// 启动静态文件服务
27-
staticApp.listen(staticPort, () => {
28-
console.log(`Static file server running on port http://localhost:${staticPort}`);
27+
staticApp.listen(frontEndPort, () => {
28+
console.log(`Static file server running on port http://localhost:${frontEndPort}`);
2929
});

vite.config.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import { CodeInspectorPlugin } from 'code-inspector-plugin';
66

77
dotenv.config();
88

9-
const apiPort = process.env.PORT || 11966;
9+
const backEndPort = process.env.BACKEND_PORT || 11966;
10+
const frontEndPort = process.env.FRONTEND_PORT || 18966;
1011

1112
export default defineConfig({
1213
plugins: [
@@ -85,9 +86,9 @@ export default defineConfig({
8586
},
8687
server: {
8788
host: '0.0.0.0',
88-
port: 18966,
89+
port: frontEndPort,
8990
proxy: {
90-
'/api': `http://localhost:${apiPort}`
91+
'/api': `http://localhost:${backEndPort}`
9192
}
9293
}
9394
})

0 commit comments

Comments
 (0)