本文目录导读:

我来详细解释PHP中如何实现代理功能。
简单HTTP代理
基本代理脚本
<?php
// simple_proxy.php
$target_url = $_GET['url'] ?? '';
if (empty($target_url)) {
die('请提供目标URL');
}
// 初始化cURL
$ch = curl_init();
// 设置cURL选项
curl_setopt_array($ch, [
CURLOPT_URL => $target_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10,
]);
// 转发请求头(可选)
$headers = [];
foreach(getallheaders() as $name => $value) {
if (!in_array(strtolower($name), ['host', 'connection', 'accept-encoding'])) {
$headers[] = "$name: $value";
}
}
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
// 转发POST数据
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
}
// 执行请求
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$content_type = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
// 设置响应头
http_response_code($http_code);
if ($content_type) {
header('Content-Type: ' . $content_type);
}
// 输出响应内容
echo $response;
curl_close($ch);
?>
使用示例
<!-- 在网页中使用 --> <img src="simple_proxy.php?url=https://example.com/image.jpg">
完整的代理类
<?php
class Proxy {
private $ch;
private $options = [];
private $headers = [];
public function __construct() {
$this->ch = curl_init();
$this->setDefaultOptions();
}
private function setDefaultOptions() {
$this->options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_HEADER => true, // 获取响应头
];
}
public function setOption($option, $value) {
$this->options[$option] = $value;
return $this;
}
public function setHeader($header, $value) {
$this->headers[$header] = $value;
return $this;
}
public function forward($url, $method = 'GET', $data = null) {
$this->options[CURLOPT_URL] = $url;
$this->options[CURLOPT_CUSTOMREQUEST] = $method;
// 设置请求头
if (!empty($this->headers)) {
$headers = [];
foreach ($this->headers as $key => $value) {
$headers[] = "$key: $value";
}
$this->options[CURLOPT_HTTPHEADER] = $headers;
}
// 处理POST数据
if ($data !== null) {
$this->options[CURLOPT_POSTFIELDS] = is_array($data) ? http_build_query($data) : $data;
}
// 设置所有选项
curl_setopt_array($this->ch, $this->options);
// 执行请求
$response = curl_exec($this->ch);
$info = curl_getinfo($this->ch);
// 分离头部和内容
$header_size = $info['header_size'];
$response_headers = substr($response, 0, $header_size);
$response_body = substr($response, $header_size);
return [
'headers' => $this->parseHeaders($response_headers),
'body' => $response_body,
'info' => $info,
];
}
private function parseHeaders($raw_headers) {
$headers = [];
foreach (explode("\r\n", $raw_headers) as $line) {
if (strpos($line, ': ') !== false) {
list($key, $value) = explode(': ', $line, 2);
$headers[trim($key)] = trim($value);
}
}
return $headers;
}
public function __destruct() {
curl_close($this->ch);
}
}
// 使用示例
$proxy = new Proxy();
$proxy->setHeader('User-Agent', 'Mozilla/5.0');
$result = $proxy->forward('https://api.example.com/data', 'POST', [
'param1' => 'value1',
'param2' => 'value2'
]);
print_r($result);
?>
支持Cookie的代理
<?php
class CookieAwareProxy {
private $ch;
private $cookie_file;
public function __construct($cookie_file = null) {
$this->ch = curl_init();
$this->cookie_file = $cookie_file ?? tempnam(sys_get_temp_dir(), 'cookie');
curl_setopt_array($this->ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_COOKIEFILE => $this->cookie_file,
CURLOPT_COOKIEJAR => $this->cookie_file,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_USERAGENT => 'Mozilla/5.0',
]);
}
public function request($url, $method = 'GET', $data = null) {
curl_setopt($this->ch, CURLOPT_URL, $url);
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $method);
if ($data) {
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);
}
return curl_exec($this->ch);
}
public function __destruct() {
curl_close($this->ch);
if (file_exists($this->cookie_file)) {
unlink($this->cookie_file);
}
}
}
// 使用示例
$proxy = new CookieAwareProxy();
$response = $proxy->request('https://example.com/login', 'POST', [
'username' => 'admin',
'password' => 'password'
]);
echo $response;
?>
反向代理
<?php
// reverse_proxy.php
$backend_host = 'http://backend-server:8080';
$request_uri = $_SERVER['REQUEST_URI'];
$target_url = $backend_host . $request_uri;
// 创建代理请求
$ch = curl_init($target_url);
// 设置选项
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
]);
// 转发请求方法
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD']);
// 转发请求体
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents('php://input'));
}
// 执行请求
$response = curl_exec($ch);
$info = curl_getinfo($ch);
// 分离响应头
$header_size = $info['header_size'];
$response_headers = substr($response, 0, $header_size);
$response_body = substr($response, $header_size);
// 设置响应头
foreach (explode("\r\n", $response_headers) as $header) {
if (!empty($header) && !str_starts_with(strtolower($header), 'transfer-encoding')) {
header($header);
}
}
// 输出响应
echo $response_body;
curl_close($ch);
?>
安全注意事项
<?php
class SecureProxy {
// 白名单域名
private $allowed_domains = [
'api.example.com',
'cdn.example.com',
];
// 黑名单IP
private $blocked_ips = [
'10.0.0.0/8',
'172.16.0.0/12',
'192.168.0.0/16',
];
public function isAllowed($url) {
$parsed_url = parse_url($url);
$host = $parsed_url['host'] ?? '';
// 检查白名单
if (!in_array($host, $this->allowed_domains)) {
return false;
}
// 检查IP黑名单
$ip = gethostbyname($host);
foreach ($this->blocked_ips as $blocked) {
if ($this->ipInCIDR($ip, $blocked)) {
return false;
}
}
return true;
}
private function ipInCIDR($ip, $cidr) {
list($range, $mask) = explode('/', $cidr);
$range_int = ip2long($range);
$ip_int = ip2long($ip);
$mask_int = -1 << (32 - $mask);
return ($ip_int & $mask_int) == ($range_int & $mask_int);
}
// URL验证
public function validateUrl($url) {
// 防止SSRF攻击
if (!filter_var($url, FILTER_VALIDATE_URL)) {
return false;
}
// 限制协议
$scheme = parse_url($url, PHP_URL_SCHEME);
if (!in_array($scheme, ['http', 'https'])) {
return false;
}
// 限制端口
$port = parse_url($url, PHP_URL_PORT);
if ($port && !in_array($port, [80, 443, 8080])) {
return false;
}
return true;
}
}
?>
常用配置
<?php
// 代理配置示例
$proxy_config = [
// 超时设置
'timeout' => 30,
'connect_timeout' => 10,
// 代理服务器(如果需要)
'proxy' => [
'host' => 'proxy.example.com',
'port' => 8080,
'auth' => 'username:password', // 可选
],
// 缓存设置
'cache' => [
'enabled' => true,
'ttl' => 3600, // 1小时
],
// 速率限制
'rate_limit' => [
'requests' => 100,
'period' => 60, // 每分钟
],
];
?>
PHP实现代理的主要方式:
- 简单代理:使用curl直接转发请求
- 完整代理类:封装更多功能
- Cookie支持:保持会话状态
- 反向代理:隐藏后端服务器
- 安全控制:防止滥用和攻击
根据实际需求选择合适的实现方式。