From 1b53cd4ca8edd0b68fad66473fafe2fb35072045 Mon Sep 17 00:00:00 2001 From: CityFun <31820853+zhengkunwang223@users.noreply.github.com> Date: Tue, 28 Oct 2025 18:18:18 +0800 Subject: [PATCH] feat: add sync waf ip group cron job (#10802) Refs https://github.com/1Panel-dev/1Panel/issues/8915 --- agent/app/service/cronjob_helper.go | 74 +++++++++++++++++++ frontend/src/lang/modules/en.ts | 1 + frontend/src/lang/modules/es-es.ts | 2 + frontend/src/lang/modules/ja.ts | 1 + frontend/src/lang/modules/ko.ts | 2 + frontend/src/lang/modules/ms.ts | 1 + frontend/src/lang/modules/pt-br.ts | 1 + frontend/src/lang/modules/ru.ts | 1 + frontend/src/lang/modules/tr.ts | 1 + frontend/src/lang/modules/zh-Hant.ts | 1 + frontend/src/lang/modules/zh.ts | 1 + .../views/cronjob/cronjob/operate/index.vue | 1 + 12 files changed, 87 insertions(+) diff --git a/agent/app/service/cronjob_helper.go b/agent/app/service/cronjob_helper.go index 3293e2966..39ac44c56 100644 --- a/agent/app/service/cronjob_helper.go +++ b/agent/app/service/cronjob_helper.go @@ -1,11 +1,15 @@ package service import ( + "bufio" "context" "fmt" + "io" + "net/http" "os" "path" pathUtils "path" + "path/filepath" "strings" "time" @@ -127,6 +131,8 @@ func (u *CronjobService) loadTask(cronjob *model.Cronjob, record *model.JobRecor err = u.handleDirectory(*cronjob, record.StartTime, taskItem) case "log": err = u.handleSystemLog(*cronjob, record.StartTime, taskItem) + case "syncIpGroup": + u.handleSyncIpGroup(*cronjob, taskItem) } return err } @@ -210,6 +216,74 @@ func (u *CronjobService) handleNtpSync(cronjob model.Cronjob, taskItem *task.Tas }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) } +func (u *CronjobService) handleSyncIpGroup(cronjob model.Cronjob, taskItem *task.Task) { + taskItem.AddSubTaskWithOps(i18n.GetWithName("SyncIpGroup", cronjob.Name), func(t *task.Task) error { + appInstall, err := getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return err + } + ipGroupDir := path.Join(appInstall.GetPath(), "1pwaf", "data", "rules", "ip_group") + urlDir := path.Join(ipGroupDir, "ip_group_url") + + urlsFiles, err := os.ReadDir(urlDir) + if err != nil { + return err + } + for _, file := range urlsFiles { + if file.IsDir() || !strings.HasSuffix(file.Name(), "_url") { + continue + } + urlFilePath := filepath.Join(urlDir, file.Name()) + + urlContent, err := os.ReadFile(urlFilePath) + if err != nil { + continue + } + remoteURL := strings.TrimSpace(string(urlContent)) + if remoteURL == "" { + continue + } + resp, err := http.Get(remoteURL) + if err != nil { + continue + } + + ipGroupFile := strings.TrimSuffix(file.Name(), "_url") + ipGroupPath := filepath.Join(ipGroupDir, ipGroupFile) + + if resp.StatusCode != http.StatusOK { + resp.Body.Close() + taskItem.Logf("get remote ip group %s failed %s status code %d", ipGroupFile, remoteURL, resp.StatusCode) + continue + } + + outFile, err := os.OpenFile(ipGroupPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) + if err != nil { + resp.Body.Close() + taskItem.Logf("sync %s failed %v", ipGroupFile, err) + continue + } + + writer := bufio.NewWriter(outFile) + _, err = io.Copy(writer, resp.Body) + if err != nil { + outFile.Close() + resp.Body.Close() + taskItem.Logf("sync %s failed , write file failed %v", ipGroupFile, err) + continue + } + writer.Flush() + outFile.Close() + resp.Body.Close() + taskItem.LogSuccess(i18n.Get("TaskSync") + " " + ipGroupFile) + } + if err := opNginx(appInstall.ContainerName, constant.NginxReload); err != nil { + return err + } + return nil + }, nil, int(cronjob.RetryTimes), time.Duration(cronjob.Timeout)*time.Second) +} + func (u *CronjobService) handleCutWebsiteLog(cronjob *model.Cronjob, startTime time.Time, taskItem *task.Task) error { clientMap := NewBackupClientMap([]string{fmt.Sprintf("%v", cronjob.DownloadAccountID)}) if !clientMap[fmt.Sprintf("%d", cronjob.DownloadAccountID)].isOk { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 6bf4403c9..7e2c90a76 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1142,6 +1142,7 @@ const message = { errPath: 'Backup path [{0}] error, cannot download!', cutWebsiteLog: 'Website log rotation', cutWebsiteLogHelper: 'The rotated log files will be backed up to the backup directory of 1Panel.', + syncIpGroup: 'Sync WAF IP groups', requestExpirationTime: 'Upload request expiration time(Hours)', unitHours: 'Unit: Hours', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index fed87bdf1..f5ea2eb9f 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -1144,6 +1144,8 @@ const message = { errPath: '¡Error en la ruta de respaldo [{0}], no se puede descargar!', cutWebsiteLog: 'Rotación de logs del sitio', cutWebsiteLogHelper: 'Los archivos de log rotados se respaldarán en el directorio de respaldos de 1Panel.', + syncIpGroup: 'Sincronizar grupos de IP de WAF', + requestExpirationTime: 'Tiempo de expiración de solicitud de subida (Horas)', unitHours: 'Unidad: Horas', alertTitle: 'Tarea programada - {0} 「{1}」 Alerta de fallo', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 6f1475b3a..a2cf382a9 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -1104,6 +1104,7 @@ const message = { errPath: 'バックアップパス[{0}]エラー、ダウンロードできません!', cutWebsiteLog: 'ウェブサイトのログローテーション', cutWebsiteLogHelper: '回転したログファイルは、1パネルのバックアップディレクトリにバックアップされます。', + syncIpGroup: 'WAF IP グループを同期', requestExpirationTime: 'リクエストの有効期限(時間)のアップロード', unitHours: 'ユニット:時間', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 4dbc1b032..4c69f6766 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -1098,6 +1098,8 @@ const message = { errPath: '백업 경로 [{0}] 오류, 다운로드할 수 없습니다!', cutWebsiteLog: '웹사이트 로그 회전', cutWebsiteLogHelper: '회전된 로그 파일은 1Panel 의 백업 디렉토리로 백업됩니다.', + syncIpGroup: 'WAF IP 그룹 동기화', + requestExpirationTime: '업로드 요청 만료 시간(시간)', unitHours: '단위: 시간', alertTitle: '예정된 작업 - {0} 「{1}」 작업 실패 경고', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 1da22f759..e858b152d 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -1135,6 +1135,7 @@ const message = { errPath: 'Laluan sandaran [{0}] salah, tidak boleh dimuat turun!', cutWebsiteLog: 'Putaran log laman web', cutWebsiteLogHelper: 'Fail log yang diputar akan disandarkan ke direktori sandaran 1Panel.', + syncIpGroup: 'Segerakkan kumpulan IP WAF', requestExpirationTime: 'Waktu luput permintaan muat naik (Jam)', unitHours: 'Unit: Jam', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 800a9cdeb..7ee2f1150 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -1127,6 +1127,7 @@ const message = { errPath: 'Caminho de backup [{0}] com erro, não é possível fazer o download!', cutWebsiteLog: 'Rotação de log do site', cutWebsiteLogHelper: 'Os arquivos de log rotacionados serão salvos no diretório de backup do 1Panel.', + syncIpGroup: 'Sincronizar grupos de IP do WAF', requestExpirationTime: 'Tempo de expiração da solicitação de upload (Horas)', unitHours: 'Unidade: Horas', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 712c38b55..1d1831629 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -1131,6 +1131,7 @@ const message = { errPath: 'Ошибка пути резервной копии [{0}], невозможно скачать!', cutWebsiteLog: 'Ротация логов сайта', cutWebsiteLogHelper: 'Ротированные файлы логов будут сохранены в директории резервных копий 1Panel.', + syncIpGroup: 'Синхронизировать группы IP WAF', requestExpirationTime: 'Время истечения запроса на загрузку (часы)', unitHours: 'Единица: часы', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index b5a921d3f..d363ce7bf 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -1154,6 +1154,7 @@ const message = { errPath: 'Yedek yolu [{0}] hatası, indirilemez!', cutWebsiteLog: 'Website log döndürme', cutWebsiteLogHelper: 'Döndürülen log dosyaları 1Panel yedek dizinine yedeklenecektir.', + syncIpGroup: 'WAF IP gruplarını senkronize et', requestExpirationTime: 'Yükleme isteği son kullanma süresi(Saat)', unitHours: 'Birim: Saat', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 50332bece..a40898685 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -1082,6 +1082,7 @@ const message = { errPath: '備份路徑 [{0}] 錯誤,無法下載!', cutWebsiteLog: '切割網站日誌', cutWebsiteLogHelper: '切割的日誌檔案會備份到 1Panel 的 backup 目錄下', + syncIpGroup: '同步 WAF IP 組', requestExpirationTime: '上傳請求過期時間(小時)', unitHours: '單位:小時', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index dd36032cc..46409e9af 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1083,6 +1083,7 @@ const message = { errPath: '备份路径 [{0}] 错误,无法下载!', cutWebsiteLog: '切割网站日志', cutWebsiteLogHelper: '切割的日志文件会备份到 1Panel 的 backup 目录下', + syncIpGroup: '同步 WAF IP 组', requestExpirationTime: '上传请求过期时间(小时)', unitHours: '单位:小时', diff --git a/frontend/src/views/cronjob/cronjob/operate/index.vue b/frontend/src/views/cronjob/cronjob/operate/index.vue index 416a990f3..5578ad58b 100644 --- a/frontend/src/views/cronjob/cronjob/operate/index.vue +++ b/frontend/src/views/cronjob/cronjob/operate/index.vue @@ -26,6 +26,7 @@ +
{{ $t('cronjob.' + form.type) }}