├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── add_domain.php ├── auth.php ├── cf.class.php ├── config.php ├── delete_domain.php ├── domains.php ├── edit_record.php ├── footer.php ├── header.php ├── index.php └── manage_domain.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://blog.yuzu.im/donate'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | config.php -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 131 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CFPMP 2 | Cloudflare Partner Management Panel 3 | 4 | 打开config.php,根据里面的注释进行设置后即可使用 5 | 6 | ## 功能 7 | * CNAME接入 8 | * reCAPTCHA 9 | * 设置回源地址为IP(基于sslip.io)(默认关闭此功能) 10 | * 通过 TXT 记录验证域名是否受用户控制 11 | 12 | 可用实例:[https://cf.yuzu.im/](https://cf.yuzu.im/) 13 | -------------------------------------------------------------------------------- /add_domain.php: -------------------------------------------------------------------------------- 1 | is_login(); 5 | 6 | function msg($s) 7 | { 8 | $_SESSION["msg"] = $s; 9 | header("Location: domains.php"); 10 | exit(0); 11 | } 12 | 13 | if (empty($_POST["domain"])) { 14 | msg("域名不能为空"); 15 | } 16 | 17 | if (Enable_TXT_Verification){ 18 | if (!$cloudflare->check_txt_record($_POST["domain"])){ 19 | msg("TXT 记录验证失败"); 20 | } 21 | } 22 | 23 | $r = $cloudflare->zone_set($_POST["domain"], $_POST["domain"], "www:" . $_POST["domain"]); 24 | 25 | if ($r["result"] == "success") { 26 | msg("添加成功"); 27 | } else { 28 | if (empty($r["msg"])) { 29 | msg("请刷新本页面以确认域名是否添加成功"); 30 | } else { 31 | msg("添加失败:" . $r["msg"]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /auth.php: -------------------------------------------------------------------------------- 1 | reCAPTCHA($_POST["g-recaptcha-response"]))) { 15 | msg("请完成验证码"); 16 | } 17 | } else { 18 | msg("请完成验证码"); 19 | } 20 | } 21 | 22 | if ((!empty($_POST["email"])) && (!empty($_POST["password"]))) { 23 | $r = $cloudflare->login($_POST["email"], $_POST["password"]); 24 | if ($r["result"] == "success") { 25 | $_SESSION["user_key"] = $r["response"]["user_key"]; 26 | $_SESSION["email"] = $r["response"]["cloudflare_email"]; 27 | $_SESSION["api_key"] = $r["response"]["user_api_key"]; 28 | //if (Enable_TXT_Verification) $_SESSION["txt_verification"] = password_hash(Random_String.$_SESSION["email"],PASSWORD_BCRYPT ); 29 | header("Location: domains.php"); 30 | } else { 31 | msg("失败:" . $r["msg"]); 32 | } 33 | } else { 34 | msg("用户名和密码不能为空"); 35 | } 36 | -------------------------------------------------------------------------------- /cf.class.php: -------------------------------------------------------------------------------- 1 | "CNAME", 138 | "name" => $name, 139 | "content" => self::add_suffix_for_ip($content), 140 | "ttl" => 1, 141 | "proxied" => true 142 | ]); 143 | } 144 | 145 | public function edit_record($zone_id, $record_id, $name, $content){ 146 | return self::user_api_post("https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id", [ 147 | 'type' => 'CNAME', 148 | 'name' => $name, 149 | 'content' => self::add_suffix_for_ip($content), 150 | 'ttl' => 1, 151 | "proxied" => true 152 | ], "PUT"); 153 | } 154 | 155 | public function delete_record($zone_id, $record_id){ 156 | $data = self::user_api_post("https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id", [], "DELETE"); 157 | $data['result']['id']==$record_id ? $data['success'] = true : $data['success'] = false; 158 | return $data; 159 | } 160 | 161 | public function add_suffix_for_ip($content){ 162 | if (Enable_A_Record&&(filter_var($content, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))){ 163 | return $content.".sslip.io"; 164 | }else{ 165 | return $content; 166 | } 167 | } 168 | 169 | public function reCAPTCHA($response) 170 | { 171 | $url = "https://www.recaptcha.net/recaptcha/api/siteverify"; 172 | $data = array( 173 | "secret" => reCAPTCHA_Secret, 174 | "response" => $response 175 | ); 176 | $ch = curl_init(); 177 | curl_setopt($ch, CURLOPT_URL, $url); 178 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 179 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 180 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 181 | $r = curl_exec($ch); 182 | curl_close($ch); 183 | $re = json_decode($r, true); 184 | if (!empty($re["success"])) { 185 | if ($re["success"] == "true") { 186 | return true; 187 | } else { 188 | return false; 189 | } 190 | } else { 191 | return false; 192 | } 193 | } 194 | 195 | public function check_txt_record($domain){ 196 | foreach(dns_get_record("cfpmp.".$domain, DNS_TXT) as $v){ 197 | if (password_verify(Random_String.$_SESSION["email"], $v["txt"])) return true; 198 | } 199 | return false; 200 | } 201 | } 202 | 203 | $cloudflare = new CF(); -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | is_login(); 5 | 6 | function msg($s) 7 | { 8 | $_SESSION["msg"] = $s; 9 | header("Location: domains.php"); 10 | exit(0); 11 | } 12 | 13 | if (empty($_POST["domain"])) { 14 | msg("域名不能为空"); 15 | } 16 | 17 | $r = $cloudflare->zone_delete($_POST["domain"]); 18 | 19 | if ($r["result"] == "success") { 20 | msg("删除成功"); 21 | } else { 22 | msg("删除失败:" . $r["msg"]); 23 | } -------------------------------------------------------------------------------- /domains.php: -------------------------------------------------------------------------------- 1 | is_login(); 6 | 7 | $r = $cloudflare->user_lookup(); 8 | 9 | include_once("header.php"); 10 | 11 | $output = ''; 12 | ?> 13 | 14 |