diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43777a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +config.php \ No newline at end of file diff --git a/README.md b/README.md index 2afeb3d..e1f9fff 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,10 @@ Cloudflare Partner Management Panel 打开config.php,根据里面的注释进行设置后即可使用 -English version: [https://github.com/Netrvin/CFPMP/tree/en-v0.2.3](https://github.com/Netrvin/CFPMP/tree/en-v0.2.3) - ## 功能 * CNAME接入 * reCAPTCHA * 设置回源地址为IP(基于sslip.io)(默认关闭此功能) +* 通过 TXT 记录验证域名是否受用户控制 可用实例:[https://cf.yuzu.im/](https://cf.yuzu.im/) diff --git a/add_domain.php b/add_domain.php index 59a4ae1..f2608c2 100644 --- a/add_domain.php +++ b/add_domain.php @@ -3,24 +3,31 @@ $cloudflare->is_login(); -function msg($s){ - $_SESSION["msg"]=$s; +function msg($s) +{ + $_SESSION["msg"] = $s; header("Location: domains.php"); exit(0); } -if (empty($_POST["domain"])){ +if (empty($_POST["domain"])) { msg("域名不能为空"); } -$r=$cloudflare->zone_set($_POST["domain"],$_POST["domain"],"www:".$_POST["domain"]); +if (Enable_TXT_Verification){ + if (!$cloudflare->check_txt_record($_POST["domain"])){ + msg("TXT 记录验证失败"); + } +} + +$r = $cloudflare->zone_set($_POST["domain"], $_POST["domain"], "www:" . $_POST["domain"]); -if ($r["result"]=="success"){ +if ($r["result"] == "success") { msg("添加成功"); -}else{ - if (empty($r["msg")){ +} else { + if (empty($r["msg"])) { msg("请刷新本页面以确认域名是否添加成功"); - }else{ - msg("添加失败:".$r["msg"]); + } else { + msg("添加失败:" . $r["msg"]); } } diff --git a/auth.php b/auth.php index 14bee04..b9bf75d 100644 --- a/auth.php +++ b/auth.php @@ -2,36 +2,33 @@ include_once("cf.class.php"); -function msg($s){ - $_SESSION["login_msg"]=$s; +function msg($s) +{ + $_SESSION["login_msg"] = $s; header("Location: index.php"); exit(0); } -if (Enable_reCAPTCHA) -{ - if (!empty($_POST["g-recaptcha-response"])) - { - if (!($cloudflare->reCAPTCHA($_POST["g-recaptcha-response"]))) - { +if (Enable_reCAPTCHA) { + if (!empty($_POST["g-recaptcha-response"])) { + if (!($cloudflare->reCAPTCHA($_POST["g-recaptcha-response"]))) { msg("请完成验证码"); } - }else{ + } else { msg("请完成验证码"); } } -if ((!empty($_POST["email"]))&&(!empty($_POST["password"]))) -{ - $r=$cloudflare->login($_POST["email"],$_POST["password"]); - if ($r["result"]=="success") - { - $_SESSION["user_key"]=$r["response"]["user_key"]; - $_SESSION["email"]=$r["response"]["cloudflare_email"]; +if ((!empty($_POST["email"])) && (!empty($_POST["password"]))) { + $r = $cloudflare->login($_POST["email"], $_POST["password"]); + if ($r["result"] == "success") { + $_SESSION["user_key"] = $r["response"]["user_key"]; + $_SESSION["email"] = $r["response"]["cloudflare_email"]; + if (Enable_TXT_Verification) $_SESSION["txt_verification"] = password_hash(Random_String.$_SESSION["email"],PASSWORD_BCRYPT ); header("Location: domains.php"); - }else{ - msg("登录 / 注册失败:".$r["msg"]); + } else { + msg("失败:" . $r["msg"]); } -}else{ +} else { msg("用户名和密码不能为空"); } diff --git a/cf.class.php b/cf.class.php index e66dedd..ace8773 100644 --- a/cf.class.php +++ b/cf.class.php @@ -2,116 +2,129 @@ include_once("config.php"); +if (Enable_TXT_Verification&&(strlen(Random_String)<64)){ + die("Please set Random_String in config.php or disable TXT record verification"); +} + session_start(); -class CF { - public function post($data){ - $data["host_key"]=HOST_KEY; - $ch=curl_init(); - curl_setopt($ch,CURLOPT_URL,"https://api.cloudflare.com/host-gw.html"); - curl_setopt($ch,CURLOPT_POSTFIELDS,$data); - curl_setopt($ch,CURLOPT_TIMEOUT,10); - curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); - $r=curl_exec($ch); +class CF +{ + public function post($data) + { + $data["host_key"] = HOST_KEY; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "https://api.cloudflare.com/host-gw.html"); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $r = curl_exec($ch); curl_close($ch); - return json_decode($r,true); + return json_decode($r, true); } - public function login($email,$password){ - $data["act"]="user_create"; - $data["cloudflare_email"]=$email; - $data["cloudflare_pass"]=$password; - $data["unique_id"]=NULL; - return self::post($data); + public function login($email, $password) + { + $data["act"] = (Allow_Register ? "user_create" : "user_auth"); + $data["cloudflare_email"] = $email; + $data["cloudflare_pass"] = $password; + $data["unique_id"] = NULL; + return self::post($data); } - public function logout(){ - if (!empty($_SESSION["email"])){ + public function logout() + { + if (!empty($_SESSION["email"])) { unset($_SESSION["email"]); } - if (!empty($_SESSION["user_key"])){ + if (!empty($_SESSION["user_key"])) { unset($_SESSION["user_key"]); } } - public function is_login(){ - if ((empty($_SESSION["email"]))||(empty($_SESSION["user_key"]))){ + public function is_login() + { + if ((empty($_SESSION["email"])) || (empty($_SESSION["user_key"]))) { header("Location: index.php"); exit(0); } } - public function user_lookup(){ - $data["act"]="user_lookup"; - $data["cloudflare_email"]=$_SESSION["email"]; - return self::post($data); - } - - public function zone_set($zone_name,$resolve_to,$subdomains){ - $data["act"] = "zone_set"; - $data["user_key"] = $_SESSION["user_key"]; - $data["zone_name"] = $zone_name; - $data["resolve_to"] = $resolve_to; - $data["subdomains"] = $subdomains; - return self::post($data); - } - - public function zone_delete($zone_name){ - $data["act"] = "zone_delete"; - $data["user_key"] = $_SESSION["user_key"]; - $data["zone_name"] = $zone_name; - return self::post($data); - } - - public function zone_lookup($zone_name){ - $data["act"] = "zone_lookup"; - $data["user_key"] = $_SESSION["user_key"]; - $data["zone_name"] = $zone_name; - return self::post($data); - } - - public function update_record($zone_name,$record){ - if (empty($record["@"])){ - $record["@"]=$zone_name; + public function user_lookup() + { + $data["act"] = "user_lookup"; + $data["cloudflare_email"] = $_SESSION["email"]; + return self::post($data); + } + + public function zone_set($zone_name, $resolve_to, $subdomains) + { + $data["act"] = "zone_set"; + $data["user_key"] = $_SESSION["user_key"]; + $data["zone_name"] = $zone_name; + $data["resolve_to"] = $resolve_to; + $data["subdomains"] = $subdomains; + return self::post($data); + } + + public function zone_delete($zone_name) + { + $data["act"] = "zone_delete"; + $data["user_key"] = $_SESSION["user_key"]; + $data["zone_name"] = $zone_name; + return self::post($data); + } + + public function zone_lookup($zone_name) + { + $data["act"] = "zone_lookup"; + $data["user_key"] = $_SESSION["user_key"]; + $data["zone_name"] = $zone_name; + return self::post($data); + } + + public function update_record($zone_name, $record) + { + if (empty($record["@"])) { + $record["@"] = $zone_name; } - $at=$record["@"]; + $at = $record["@"]; unset($record["@"]); - if ((Enable_A_Record) && (filter_var($at,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4))){ - $at=$at.'.sslip.io'; + if ((Enable_A_Record) && (filter_var($at, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))) { + $at = $at . '.sslip.io'; } - $str=""; - foreach ($record as $key => $value){ - if ((Enable_A_Record) && (filter_var($value,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4))){ - $str.=$key.":".$value.".sslip.io,"; - }else{ - $str.=$key.":".$value.","; + $str = ""; + foreach ($record as $key => $value) { + if ((Enable_A_Record) && (filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))) { + $str .= $key . ":" . $value . ".sslip.io,"; + } else { + $str .= $key . ":" . $value . ","; } } - if (empty($str)){ - $str="www:".$zone_name; - }else{ - $str=substr($str,0,strlen($str)-1); + if (empty($str)) { + $str = "www:" . $zone_name; + } else { + $str = substr($str, 0, strlen($str) - 1); } - return self::zone_set($zone_name,$at,$str); + return self::zone_set($zone_name, $at, $str); } - public function remove_zone_name($zone_name,$data){ - foreach ($data["hosted_cnames"] as $record => $set) - { - if (strlen($record) > strlen($zone_name)){ - $record2 = substr($record,0,strlen($record)-strlen($zone_name)-1); - }else{ - $record2="@"; + public function remove_zone_name($zone_name, $data) + { + foreach ($data["hosted_cnames"] as $record => $set) { + if (strlen($record) > strlen($zone_name)) { + $record2 = substr($record, 0, strlen($record) - strlen($zone_name) - 1); + } else { + $record2 = "@"; } $data["hosted_cnames"][$record2] = $set; unset($data["hosted_cnames"][$record]); } - foreach ($data["forward_tos"] as $record => $set) - { - if (strlen($record) > strlen($zone_name)){ - $record2 = substr($record,0,strlen($record)-strlen($zone_name)-1); - }else{ - $record2="@"; + foreach ($data["forward_tos"] as $record => $set) { + if (strlen($record) > strlen($zone_name)) { + $record2 = substr($record, 0, strlen($record) - strlen($zone_name) - 1); + } else { + $record2 = "@"; } $data["forward_tos"][$record2] = $set; unset($data["forward_tos"][$record]); @@ -119,30 +132,38 @@ public function remove_zone_name($zone_name,$data){ return $data; } - public function reCAPTCHA($response){ - $url= "https://www.recaptcha.net/recaptcha/api/siteverify"; - $data=array ( + public function reCAPTCHA($response) + { + $url = "https://www.recaptcha.net/recaptcha/api/siteverify"; + $data = array( "secret" => reCAPTCHA_Secret, "response" => $response ); - $ch=curl_init(); - curl_setopt($ch,CURLOPT_URL,$url); - curl_setopt($ch,CURLOPT_POSTFIELDS,$data); - curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); - curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10); - $r=curl_exec($ch); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + $r = curl_exec($ch); curl_close($ch); - $re=json_decode($r,true); - if (!empty($re["success"])){ - if ($re["success"]=="true"){ + $re = json_decode($r, true); + if (!empty($re["success"])) { + if ($re["success"] == "true") { return true; - }else{ + } else { return false; } - }else{ + } else { return false; } - } + } + + public function check_txt_record($domain){ + foreach(dns_get_record("cfpmp.".$domain, DNS_TXT) as $v){ + if (password_verify(Random_String.$_SESSION["email"], $v["txt"])) return true; + } + return false; + } } -$cloudflare=new CF(); \ No newline at end of file +$cloudflare = new CF(); \ No newline at end of file diff --git a/config.php b/config.php index a1bccde..2b96f32 100644 --- a/config.php +++ b/config.php @@ -1,15 +1,22 @@ is_login(); -function msg($s){ - $_SESSION["msg"]=$s; +function msg($s) +{ + $_SESSION["msg"] = $s; header("Location: domains.php"); exit(0); } -if (empty($_POST["domain"])){ +if (empty($_POST["domain"])) { msg("域名不能为空"); } -$r=$cloudflare->zone_delete($_POST["domain"]); +$r = $cloudflare->zone_delete($_POST["domain"]); -if ($r["result"]=="success"){ +if ($r["result"] == "success") { msg("删除成功"); -}else{ - msg("删除失败:".$r["msg"]); +} else { + msg("删除失败:" . $r["msg"]); } \ No newline at end of file diff --git a/domains.php b/domains.php index 62ea686..0a40399 100644 --- a/domains.php +++ b/domains.php @@ -4,7 +4,7 @@ $cloudflare->is_login(); -$r=$cloudflare->user_lookup(); +$r = $cloudflare->user_lookup(); include_once("header.php"); @@ -12,133 +12,140 @@ ?>
-
-
- -
-
- Cloudflare Partners : - - > - 域名管理 -
-
-
-
- . - 登出 -
-
- - -
-
-
- - - -
-
-
- - - - - - - - - - +
+ +
+
+ Cloudflare Partners : + + > + 域名管理 +
+
+
+
+ . + 登出 +
+
+ + +
+
+
+ + + +
+
+
+
域名
+ + + + + + + + + - - - + + + '; - } - echo $output; - ?> - -
域名
'.$value.'管理删除' . $value . '管理删除
+ } + echo $output; + ?> + + +
+ + +

查询失败: + + + +

无域名,赶紧添加一个吧!

+ + +
+
- -

查询失败: - - - -

无域名,赶紧添加一个吧!

- - -
-
- -
-
添加域名
-
-
-
- - -
-
-
- - -
-
+
添加域名
+
+
+
+ + +
+ +

+ 请在此域名添加名称为 cfpmp 的 TXT 记录此记录可在验证完毕后删除 +

+ +
+
+ + +
+
-
删除域名
-
+
删除域名
+ +
+ 你确定要删除域名 + + + 吗? +
+
+ + +
+
+
+ +
- 你确定要删除域名 - - - 吗? +
- - +
- -
- -
-
- -
-
- -
var inst = new mdui.Dialog("#msg_dialog",{ history: false @@ -146,9 +153,9 @@ function delete_domain(domain) { inst.open(); SCRIPT; -if (!empty($_SESSION["msg"])){ - echo $msg_script; - unset($_SESSION["msg"]); +if (!empty($_SESSION["msg"])) { + echo $msg_script; + unset($_SESSION["msg"]); } include_once("footer.php"); diff --git a/edit_record.php b/edit_record.php index 7daebf9..e22721b 100644 --- a/edit_record.php +++ b/edit_record.php @@ -3,67 +3,62 @@ $cloudflare->is_login(); -function msg($s){ - $_SESSION["mng_msg"]=$s; - header("Location: manage_domain.php?domain=".$_POST["domain"]); +function msg($s) +{ + $_SESSION["mng_msg"] = $s; + header("Location: manage_domain.php?domain=" . $_POST["domain"]); exit(0); } -if (empty($_POST["domain"])){ - $_SESSION["msg"]="域名不能为空"; +if (empty($_POST["domain"])) { + $_SESSION["msg"] = "域名不能为空"; header("Location: domains.php"); exit(0); } -if (empty($_POST["action"])){ +if (empty($_POST["action"])) { msg("操作不存在"); } -if (empty($_POST["record"])){ +if (empty($_POST["record"])) { msg("记录不能为空"); } -$re=$cloudflare->zone_lookup($_POST["domain"]); -if ($re["result"]!="success"){ - msg("操作失败:".$re["msg"]); +$re = $cloudflare->zone_lookup($_POST["domain"]); +if ($re["result"] != "success") { + msg("操作失败:" . $re["msg"]); } -if ($re["response"]["zone_exists"]!=true){ +if ($re["response"]["zone_exists"] != true) { msg("该域名未在Cloudflare接入"); } -if ($re["response"]["zone_hosted"]!=true){ - msg("该域名未在".SITE_NAME."接入"); +if ($re["response"]["zone_hosted"] != true) { + msg("该域名未在" . SITE_NAME . "接入"); } -$r=$cloudflare->remove_zone_name($re["response"]["zone_name"],$re["response"]); +$r = $cloudflare->remove_zone_name($re["response"]["zone_name"], $re["response"]); -if ($_POST["action"]=="delete") -{ - if (!empty($r["hosted_cnames"][$_POST["record"]])) - { +if ($_POST["action"] == "delete") { + if (!empty($r["hosted_cnames"][$_POST["record"]])) { unset($r["hosted_cnames"][$_POST["record"]]); - $result=$cloudflare->update_record($r["zone_name"],$r["hosted_cnames"]); - if ($result["result"]=="success") - { + $result = $cloudflare->update_record($r["zone_name"], $r["hosted_cnames"]); + if ($result["result"] == "success") { msg("删除成功"); - }else{ - msg("删除失败:".$result["msg"]); + } else { + msg("删除失败:" . $result["msg"]); } - }else{ + } else { msg("记录不存在"); } -}elseif($_POST["action"]=="edit") -{ - if (!empty($_POST["value"])) - { - $r["hosted_cnames"][$_POST["record"]]=$_POST["value"]; - $result=$cloudflare->update_record($r["zone_name"],$r["hosted_cnames"]); - if ($result["result"]=="success") - { +} elseif ($_POST["action"] == "edit") { + if (!empty($_POST["value"])) { + $r["hosted_cnames"][$_POST["record"]] = $_POST["value"]; + $result = $cloudflare->update_record($r["zone_name"], $r["hosted_cnames"]); + if ($result["result"] == "success") { msg("更新成功"); - }else{ - msg("更新失败:".$result["msg"]); + } else { + msg("更新失败:" . $result["msg"]); } - }else{ + } else { msg("缺少参数"); } } diff --git a/footer.php b/footer.php index 00ebc01..172f7e7 100644 --- a/footer.php +++ b/footer.php @@ -1,13 +1,13 @@ -
+
Supported by - + . -
+
- CFPMP v0.2.3 + CFPMP v0.3.0
diff --git a/header.php b/header.php index d265540..1090236 100644 --- a/header.php +++ b/header.php @@ -3,16 +3,16 @@ - <?php echo SITE_NAME;?> - Cloudflare Partners - - - - - - - - - + <?php echo SITE_NAME; ?> - Cloudflare Partners + + + + + + + + + diff --git a/index.php b/index.php index 36fa587..152df37 100644 --- a/index.php +++ b/index.php @@ -7,69 +7,72 @@ include_once("header.php"); ?> -
-
-
+
+
+
-
-
- Cloudflare Partners : - -
-
-
-
+
+
+ Cloudflare Partners : + +
+
+
+
-
-
-
-
+
+
+
+ -
-

登入 - -

-
-
- - -
+
+

登入 + +

+
+
+ + +
-
- - -
+
+ + +
- -
- + +
+ -
-
- +
+
+ +
+
+ + +
+
-
- -
+
-
-
-
-
-
-
- -
-
- -
-
+
+
+ +
+
+ +
+
var inst = new mdui.Dialog("#error",{ history: false @@ -77,10 +80,9 @@ inst.open(); SCRIPT; -if (!empty($_SESSION["login_msg"])) -{ - echo $error; - unset($_SESSION["login_msg"]); +if (!empty($_SESSION["login_msg"])) { + echo $error; + unset($_SESSION["login_msg"]); } include_once("footer.php"); ?> \ No newline at end of file diff --git a/manage_domain.php b/manage_domain.php index 6befac5..22d2190 100644 --- a/manage_domain.php +++ b/manage_domain.php @@ -4,213 +4,213 @@ $cloudflare->is_login(); -function msg($s){ - $_SESSION["msg"]=$s; +function msg($s) +{ + $_SESSION["msg"] = $s; header("Location: domains.php"); exit(0); } -if (empty($_GET["domain"])) -{ +if (empty($_GET["domain"])) { msg("域名不能为空"); } -$re=$cloudflare->zone_lookup($_GET["domain"]); -if ($re["result"]!="success") -{ - msg("查询失败:".$re["msg"]); +$re = $cloudflare->zone_lookup($_GET["domain"]); +if ($re["result"] != "success") { + msg("查询失败:" . $re["msg"]); } -if ($re["response"]["zone_exists"]!=true) -{ +if ($re["response"]["zone_exists"] != true) { msg("该域名未在Cloudflare接入"); } -if ($re["response"]["zone_hosted"]!=true) -{ - msg("该域名未在".SITE_NAME."接入"); +if ($re["response"]["zone_hosted"] != true) { + msg("该域名未在" . SITE_NAME . "接入"); } -$r=$cloudflare->remove_zone_name($re["response"]["zone_name"],$re["response"]); +$r = $cloudflare->remove_zone_name($re["response"]["zone_name"], $re["response"]); include_once("header.php"); ?> -
+
-
- -
- -
- . - 登出 -
-
+
-
-
+ +
+ . + 登出 +
+
-
- - - - - - - - - - - $set) - { - $is_ssl=false; - if (substr($set,strlen($set) - 12)=="comodoca.com") - { - $is_ssl=true; - } - if ((Enable_A_Record) && (filter_var(str_replace('.sslip.io','',$set),FILTER_VALIDATE_IP,FILTER_FLAG_IPV4))){ - $set=str_replace('.sslip.io','',$set); - } - echo "". - ''. - "'; - } - ?> - -
记录CNAME记录回源地址
".$record.""; - if ($is_ssl) - { - echo $set; - }else{ - echo $r["forward_tos"][$record]; - } - echo ''.$set.'
-
-

- 注 (1):必须设置一个www记录,否则会自动设置一个回源地址为www记录。本记录可不在DNS服务商配置 -

-

- 注 (2):根据先前的测试(2018-02-15),目前启用Universal SSL无需再专门配置CNAME记录,只需配置所需接入的域名的CNAME记录。证书将在24小时内下发。一切以实际情况为准 -

- -

- 注 (3):回源地址以CNAME形式填写,暂时不支持A记录和AAAA记录 -

- +
+
+
+ +
+ + + + + + + + + + + $set) { + $is_ssl = false; + if (substr($set, strlen($set) - 12) == "comodoca.com") { + $is_ssl = true; + } + if ((Enable_A_Record) && (filter_var(str_replace('.sslip.io', '', $set), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))) { + $set = str_replace('.sslip.io', '', $set); + } + echo "" . + '' . + "'; + } + ?> + +
+ + 记录CNAME记录回源地址
" . $record . ""; + if ($is_ssl) { + echo $set; + } else { + echo $r["forward_tos"][$record]; + } + echo '' . $set . '
+
+

+ 注 + (1):必须设置一个www记录,否则会自动设置一个回源地址为www记录。本记录可不在DNS服务商配置 +

+

+ 注 (2):根据先前的测试(2018-02-15),目前启用Universal + SSL无需再专门配置CNAME记录,只需配置所需接入的域名的CNAME记录。证书将在24小时内下发。一切以实际情况为准 +

+ +

+ 注 (3):回源地址以CNAME形式填写,暂时不支持A记录和AAAA记录 +

+ +
+
-
-
-
+
-
+
-
-
删除记录
-
-
- - " name="domain" /> - 你确定要删除记录 - - - 吗? -
-
- - -
-
+
+
删除记录
+
+
+ + " name="domain"/> + 你确定要删除记录 + + + 吗? +
+
+ + +
+
-
修改记录
-
-
- - " name="domain" /> -
- - -
-
- - -
-
-
- - -
-
+
修改记录
+
+
+ + " name="domain"/> +
+ + +
+
+ + +
+
+
+ + +
+
-
- -
-
- -
+
+ +
+
+ +
var inst = new mdui.Dialog("#msg_dialog",{ history: false @@ -218,10 +218,9 @@ function edit_record(record,value){ inst.open(); SCRIPT; -if (!empty($_SESSION["mng_msg"])) -{ - echo $msg_script; - unset($_SESSION["mng_msg"]); +if (!empty($_SESSION["mng_msg"])) { + echo $msg_script; + unset($_SESSION["mng_msg"]); } include_once("footer.php");