博客 (27)

前提:

  • 监控摄像头有推流功能

  • 抖音有直播权限(粉丝数超过 1000)

  • 一个已备案的域名


流媒体服务器抖音直播流程.png

名词解释:

推流地址:由阿里云生成的接收摄像头视频流推送的地址。

播流地址:由阿里云生成可用于终端播放的视频流地址。


各环节功能解释:

摄像头:负责采集视频信息,并推送到阿里云。

阿里云视频直播服务:接收视频推流并分发到用户端(收费)。

OBS 软件:负责将视频流转化为可供直播伴侣调用的视频源。

直播伴侣:将视频源分发到短视频终端用户。


第一步:配置阿里云视频直播服务

1.1 在阿里云控制台中开通视频直播,在域名管理中添加域名。

image.png

这里需要添加两个域名,一个是推流域名,一个是播流域名。顾名思义,“推流”指从摄像头将流推送到阿里云,“播流”是用户播放视频流。

以添加域名推流域名“rtmp.xoyozo.net”和播流域名“live.xoyozo.net”为例:

image.png

然后按列表中的 CNAME 地址对域名作解析即可。

解析生效后,点击任意一个域名进行配置,将推流域名和播流域名相互绑定。成功后,可以在推流域名中的播流信息中看到播流域名,在播流域名的推流信息中也能看到推流域名。

1.2 生成推流地址/播流地址

在工具箱中点击地址生成器。

image.png

选择推流域名和播流域名,AppName 和 StreamName 任意填写,生成成功后获取以下地址:

image.png

注:鉴权串是按照鉴权规则生成的串,默认有效期 30 分钟,超出时间即中断推流。可以在域名管理中修改该值,或直接关闭 URL 鉴权。


第二步:在摄像机控制面板中配置推流域名

该步骤因摄像机的品牌和型号不同而有所差异。本文以 IP CAMERA 为例。

首先使用 IP 搜索工具在局域网上搜索摄像机,找到摄像机的 IP 地址。

image.png

在浏览器上打开,输入用户名和密码进入管理面板。

image.png

在“参数设置”-“网络设置”- RTMP Publish 中,将推流地址填入到“预定网址”中,点击“应用”。

image.png

刷新后查看“直播状态”和“直播网址”是否已生效。

若配置成功,可将播流地址在视频播放器中打开观看,或直接在 iPhone 或安卓手机中打开播流地址。


第三步:使用 OBS Studio 将直播流信号转换为虚拟摄像头信号

因抖音直播伴侣无法使用播流地址作为视频源进行直播输出,故使用 OBS 将播流信号转化为虚拟的本机摄像头信号源供直播伴侣调用。

下载安装 OBS Studio,添加一个“场景”:

image.png

然后添加一个“媒体源”:

image.png

去掉“本地文件”前面的勾,将播流地址填到“输入”框中:

image.png

确定后即可预览到直播内容:

image.png

拖动视频区域可调整输出范围。

点击“启动虚拟摄像机”。

提示:OBS 创建的虚拟摄像机默认会从物理麦克风和桌面系统音频拾音,请按需在“混音器”中配置。


第四步:OBS 使用 VLC 视频源(此步可略过)

若 OBS 直接添加媒体源不稳定,可以使用 VLC 视频源。

下载安装 VLC 播放器

在 OBS Studio 中添加来源,选择“VLC 视频源”:

image.png

点击“播放列表”右侧的“+”,选择“添加路径 /URL”:

image.png

填写播流地址并确定。


第五步:配置抖音直播伴侣使用 OBS 的虚拟摄像机信号源

下载安装抖音直播伴侣,在任意场景中添加素材,选择“摄像头”:

image.png

摄像头选择“OBS Virtual Camera”:

image.png

点击“开始直播”:

image.png


下一步:如何配置视频号/微博直播的推流直播监控摄像头画面

xoyozo 3 年前
7,291
返回状态ASP.NET MVCASP.NET CoreASP.NET Web API
200 视图return View();return View();-
200 带模型的视图return View(Model);return View(Model);-
200 空内容return new EmptyResult();return Ok();return Ok();
200 文本
return Content(string);return Ok(string);
return Content(string);
return Ok(string);
return Content(string);
200 JSONreturn Json(object);

return Json(T); // 强制 JSON

return Ok(T); // 请求时可指定 Content-Type

return Json(T); // 强制 JSON

return Ok(T); // 请求时可指定 Content-Type

200 JaveScriptreturn JavaScript(string script);

200 文件return File();

return File();

return PhysicalFile();

return File();

return PhysicalFile();

201 已创建

return Created(location, content);

用于 Post 接口

301 永久跳转

return RedirectPermanent(url);

return RedirectToActionPermanent(url);

return RedirectToRoutePermanent(object);

return RedirectPermanent(url);

return RedirectToActionPermanent(url);

return RedirectToRoutePermanent(object);


302 临时跳转

return Redirect(url);

return RedirectToAction(url);

return RedirectToRoute(object);

return Redirect(url);

return RedirectToAction(url);

return RedirectToRoute(object);

return Redirect(url);

return RedirectToRoute(object);

400 错误的请求return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest);return BadRequest(msg);return BadRequest(msg);
401 未授权return new HttpUnauthorizedResult("描述");return Unauthorized(msg);return Unauthorized(msg);
404 找不到文件或目录return HttpNotFound(); return NotFound(msg);return NotFound(msg);
直接指定状态码

return new HttpStatusCodeResult(HttpStatusCode.*);


public enum HttpStatusCode

{

//

// 摘要:

//     等效于 HTTP 状态 100。 System.Net.HttpStatusCode.Continue 指示客户端可能继续其请求。

Continue = 100,

//

// 摘要:

//     等效于 HTTP 状态 101。 System.Net.HttpStatusCode.SwitchingProtocols 指示正在更改协议版本或协议。

SwitchingProtocols = 101,

//

// 摘要:

//     等效于 HTTP 状态 200。 System.Net.HttpStatusCode.OK 指示请求成功,且请求的信息包含在响应中。 这是最常接收的状态代码。

OK = 200,

//

// 摘要:

//     等效于 HTTP 状态 201。 System.Net.HttpStatusCode.Created 指示请求导致在响应被发送前创建新资源。

Created = 201,

//

// 摘要:

//     等效于 HTTP 状态 202。 System.Net.HttpStatusCode.Accepted 指示已接受请求做进一步处理。

Accepted = 202,

//

// 摘要:

//     等效于 HTTP 状态 203。 System.Net.HttpStatusCode.NonAuthoritativeInformation 指示返回的元信息来自缓存副本而不是原始服务器,因此可能不正确。

NonAuthoritativeInformation = 203,

//

// 摘要:

//     等效于 HTTP 状态 204。 System.Net.HttpStatusCode.NoContent 指示已成功处理请求并且响应已被设定为无内容。

NoContent = 204,

//

// 摘要:

//     等效于 HTTP 状态 205。 System.Net.HttpStatusCode.ResetContent 指示客户端应重置(而非重新加载)当前资源。

ResetContent = 205,

//

// 摘要:

//     等效于 HTTP 状态 206。 System.Net.HttpStatusCode.PartialContent 指示响应是包括字节范围的 GET 请求所请求的部分响应。

PartialContent = 206,

//

// 摘要:

//     等效于 HTTP 状态 300。 System.Net.HttpStatusCode.MultipleChoices 指示请求的信息有多种表示形式。 默认操作是将此状态视为重定向,并遵循与此响应关联的

//     Location 标头的内容。

MultipleChoices = 300,

//

// 摘要:

//     等效于 HTTP 状态 300。 System.Net.HttpStatusCode.Ambiguous 指示请求的信息有多种表示形式。 默认操作是将此状态视为重定向,并遵循与此响应关联的

//     Location 标头的内容。

Ambiguous = 300,

//

// 摘要:

//     等效于 HTTP 状态 301。 System.Net.HttpStatusCode.MovedPermanently 指示请求的信息已移到 Location

//     头中指定的 URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。

MovedPermanently = 301,

//

// 摘要:

//     等效于 HTTP 状态 301。 System.Net.HttpStatusCode.Moved 指示请求的信息已移到 Location 头中指定的 URI

//     处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求将使用 GET 方法。

Moved = 301,

//

// 摘要:

//     等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Found 指示请求的信息位于 Location 标头中指定的 URI

//     处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求将使用 GET 方法。

Found = 302,

//

// 摘要:

//     等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Redirect 指示请求的信息位于 Location 标头中指定的

//     URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求将使用 GET 方法。

Redirect = 302,

//

// 摘要:

//     等效于 HTTP 状态 303。 作为 POST 的结果,System.Net.HttpStatusCode.SeeOther 将客户端自动重定向到 Location

//     标头中指定的 URI。 用 GET 生成对 Location 标头所指定的资源的请求。

SeeOther = 303,

//

// 摘要:

//     等效于 HTTP 状态 303。 作为 POST 的结果,System.Net.HttpStatusCode.RedirectMethod 将客户端自动重定向到

//     Location 标头中指定的 URI。 用 GET 生成对 Location 标头所指定的资源的请求。

RedirectMethod = 303,

//

// 摘要:

//     等效于 HTTP 状态 304。 System.Net.HttpStatusCode.NotModified 指示客户端的缓存副本是最新的。 未传输此资源的内容。

NotModified = 304,

//

// 摘要:

//     等效于 HTTP 状态 305。 System.Net.HttpStatusCode.UseProxy 指示请求应使用位于 Location 标头中指定的

//     URI 的代理服务器。

UseProxy = 305,

//

// 摘要:

//     等效于 HTTP 状态 306。 System.Net.HttpStatusCode.Unused 是未完全指定的 HTTP/1.1 规范的建议扩展。

Unused = 306,

//

// 摘要:

//     等效于 HTTP 状态 307。 System.Net.HttpStatusCode.TemporaryRedirect 指示请求信息位于 Location

//     标头中指定的 URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求还将使用 POST

//     方法。

TemporaryRedirect = 307,

//

// 摘要:

//     等效于 HTTP 状态 307。 System.Net.HttpStatusCode.RedirectKeepVerb 指示请求信息位于 Location

//     标头中指定的 URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求还将使用 POST

//     方法。

RedirectKeepVerb = 307,

//

// 摘要:

//     等效于 HTTP 状态 400。 System.Net.HttpStatusCode.BadRequest 指示服务器未能识别请求。 如果没有其他适用的错误,或者不知道准确的错误或错误没有自己的错误代码,则发送

//     System.Net.HttpStatusCode.BadRequest。

BadRequest = 400,

//

// 摘要:

//     等效于 HTTP 状态 401。 System.Net.HttpStatusCode.Unauthorized 指示请求的资源要求身份验证。 WWW-Authenticate

//     标头包含如何执行身份验证的详细信息。

Unauthorized = 401,

//

// 摘要:

//     等效于 HTTP 状态 402。 保留 System.Net.HttpStatusCode.PaymentRequired 以供将来使用。

PaymentRequired = 402,

//

// 摘要:

//     等效于 HTTP 状态 403。 System.Net.HttpStatusCode.Forbidden 指示服务器拒绝满足请求。

Forbidden = 403,

//

// 摘要:

//     等效于 HTTP 状态 404。 System.Net.HttpStatusCode.NotFound 指示请求的资源不在服务器上。

NotFound = 404,

//

// 摘要:

//     等效于 HTTP 状态 405。 System.Net.HttpStatusCode.MethodNotAllowed 指示请求的资源上不允许请求方法(POST

//     或 GET)。

MethodNotAllowed = 405,

//

// 摘要:

//     等效于 HTTP 状态 406。 System.Net.HttpStatusCode.NotAcceptable 指示客户端已用 Accept 标头指示将不接受资源的任何可用表示形式。

NotAcceptable = 406,

//

// 摘要:

//     等效于 HTTP 状态 407。 System.Net.HttpStatusCode.ProxyAuthenticationRequired 指示请求的代理要求身份验证。

//     Proxy-authenticate 标头包含如何执行身份验证的详细信息。

ProxyAuthenticationRequired = 407,

//

// 摘要:

//     等效于 HTTP 状态 408。 System.Net.HttpStatusCode.RequestTimeout 指示客户端没有在服务器期望请求的时间内发送请求。

RequestTimeout = 408,

//

// 摘要:

//     等效于 HTTP 状态 409。 System.Net.HttpStatusCode.Conflict 指示由于服务器上的冲突而未能执行请求。

Conflict = 409,

//

// 摘要:

//     等效于 HTTP 状态 410。 System.Net.HttpStatusCode.Gone 指示请求的资源不再可用。

Gone = 410,

//

// 摘要:

//     等效于 HTTP 状态 411。 System.Net.HttpStatusCode.LengthRequired 指示缺少必需的 Content-length

//     标头。

LengthRequired = 411,

//

// 摘要:

//     等效于 HTTP 状态 412。 System.Net.HttpStatusCode.PreconditionFailed 指示为此请求设置的条件失败,且无法执行此请求。条件是用条件请求标头(如

//     If-Match、If-None-Match 或 If-Unmodified-Since)设置的。

PreconditionFailed = 412,

//

// 摘要:

//     等效于 HTTP 状态 413。 System.Net.HttpStatusCode.RequestEntityTooLarge 指示请求太大,服务器无法处理。

RequestEntityTooLarge = 413,

//

// 摘要:

//     等效于 HTTP 状态 414。 System.Net.HttpStatusCode.RequestUriTooLong 指示 URI 太长。

RequestUriTooLong = 414,

//

// 摘要:

//     等效于 HTTP 状态 415。 System.Net.HttpStatusCode.UnsupportedMediaType 指示请求是不受支持的类型。

UnsupportedMediaType = 415,

//

// 摘要:

//     等效于 HTTP 状态 416。 System.Net.HttpStatusCode.RequestedRangeNotSatisfiable 指示无法返回从资源请求的数据范围,因为范围的开头在资源的开头之前,或因为范围的结尾在资源的结尾之后。

RequestedRangeNotSatisfiable = 416,

//

// 摘要:

//     等效于 HTTP 状态 417。 System.Net.HttpStatusCode.ExpectationFailed 指示服务器未能符合 Expect

//     标头中给定的预期值。

ExpectationFailed = 417,

//

// 摘要:

//     等效于 HTTP 状态 426。 System.Net.HttpStatusCode.UpgradeRequired 指示客户端应切换为诸如 TLS/1.0

//     之类的其他协议。

UpgradeRequired = 426,

//

// 摘要:

//     等效于 HTTP 状态 500。 System.Net.HttpStatusCode.InternalServerError 指示服务器上发生了一般错误。

InternalServerError = 500,

//

// 摘要:

//     等效于 HTTP 状态 501。 System.Net.HttpStatusCode.NotImplemented 指示服务器不支持请求的函数。

NotImplemented = 501,

//

// 摘要:

//     等效于 HTTP 状态 502。 System.Net.HttpStatusCode.BadGateway 指示中间代理服务器从另一代理或原始服务器接收到错误响应。

BadGateway = 502,

//

// 摘要:

//     等效于 HTTP 状态 503。 System.Net.HttpStatusCode.ServiceUnavailable 指示服务器暂时不可用,通常是由于过多加载或维护。

ServiceUnavailable = 503,

//

// 摘要:

//     等效于 HTTP 状态 504。 System.Net.HttpStatusCode.GatewayTimeout 指示中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时。

GatewayTimeout = 504,

//

// 摘要:

//     等效于 HTTP 状态 505。 System.Net.HttpStatusCode.HttpVersionNotSupported 指示服务器不支持请求的

//     HTTP 版本。

HttpVersionNotSupported = 505

}




附 ASP.NET Form 相关:

400:

Response.StatusCode = 400;
Response.Write("错误提示");
Response.End();


xoyozo 5 年前
3,211

image.png

使用 myssl.com 检测证书状态,显示握手失败(No FS No SNI):

image.png

发现 XP 上的 IE6 和 IE8 均无法访问该站点,原因是 XP 不支持 FS,不支持 SNI。

可以尝试在 IIS 的站点的“绑定”中更改“需要服务器名称指示”来实现正常访问。

步骤参阅:https://xoyozo.net/Blog/Details/wxpay-notify-url-https

当然,前提是服务器上必须已启用相关的协议版本和加密方式(按需启用),建议使用 IISCrypto

image.png

xoyozo 5 年前
7,071

确保磁盘未满,否则会提示各种无法连接。


  1. 在“小米WiFi”App 中开启对应路由器的“SAMBA 协议”(工具箱 - 更多工具 - SAMBA)。

  2. 在“小米WiFi”App 中开启相应电脑或设备的“全盘访问”。

  3. 通过 miwifi.com 下载安装 PC 客户端。

  4. 打开“此电脑”,“映射网络驱动器”或“添加一个网络位置”,填写路由器的地址和目录,如:“\\192.168.31.1\下载”。

  5. 如果上一步无法成功添加,那么首先需要检查 samba 服务器是否正常,可以在 iPhone 上安装“Remote File Manager”来验证。

  6. 如果 iPhone 连接正常,那么在电脑上打开“本地组策略编辑器”(命令行:gpedit.msc),在“计算机配置 - 管理模板 - 网络 - Lanman 工作站”右侧,双击“启用不安全的来宾登录”,改为“已启用”。Win7 用户参考此文


注意:电脑必须运行 PC 客户端才能访问小米路由器硬盘。

xoyozo 5 年前
14,351

原标题:关于 PHP 获取 IP 地址的几种方法


PHP 获取客户端的 IP 地址有 4 种方式:

  1. REMOTE_ADDR:浏览当前页面的用户计算机的 IP 地址

  2. HTTP_X_FORWARDED_FOR:记录代理信息,会把每一层代理都记录

  3. HTTP_CLIENT_IP:客户端的 IP

  4. X-Real-IP:没有标准,由上一跳决定


REMOTE_ADDR 一般是不能伪造的,因为是通过服务器与客户端握手协议来获取的。而 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP 是在 header 信息里面,所以客户端是可以进行很轻松的伪造。下面是对这三种方式详解:

https://www.v2ex.com/t/230367

https://www.test404.com/post-1448.html

https://www.cnblogs.com/mypath/articles/5239687.html


一、关于 REMOTE_ADDR
这个变量获取到的是“直接来源”的 IP 地址,所谓“直接来源”指的是直接请求该地址的客户端 IP 。这个 IP 在单服务器的情况下,很准确的是客户端 IP ,无法伪造。当然并不是所有的程序都一定是单服务器,比如在采用负载均衡的情况(比如采用 haproxy 或者 nginx 进行负载均衡),这个 IP 就是转发机器的 IP ,因为过程是客户端 -> 负载均衡 -> 服务端。是由负载均衡直接访问的服务端而不是客户端。


二、关于 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP
基于“一”,在负载均衡的情况下直接使用 REMOTE_ADDR 是无法获取客户端 IP 的,这就是一个问题,必须解决。于是就衍生出了负载均衡端将客户端 IP 加入到 HEAD 中发送给服务端,让服务端可以获取到客户端的真实 IP 。当然也就产生了各位所说的伪造,毕竟 HEAD 除了协议里固定的那几个数据,其他数据都是可自定义的。


三、为何网上找到获取客户端 IP 的代码都要依次获取 HTTP_CLIENT_IP 、 HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR
基于“一”和“二”以及对程序通用性的考虑,所以才这样做。 假设你在程序里直接写死了 REMOTE_ADDR ,有一天你们的程序需要做负载均衡了,那么你有得改了。当然如果你想这么做也行,看个人爱好和应用场景。也可以封装一个只有 REMOTE_ADDR 的方法,等到需要的时候改这一个方法就行了。


X_FORWARDED_FOR 与 X-Real-IP 的区别:

X_FORWARDED_FOR:记录了所有链路里的代理 IP 值,比如下面所说的,经过了 3 次代理,分别是 1.1.1.1, 2.2.2.2, 3.3.3.3,其中 1.1.1.1 是客户端 IP,2.2.2.2 是代理服务器,接下来同理。

X-Real-IP:是只会记录前一次代理的 IP 地址。

一般来说,X-Forwarded-For是用于记录代理信息的,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加在X-Forwarded-For

来自4.4.4.4的一个请求,header 包含这样一行

X-Forwarded-For: 1.1.1.1, 2.2.2.2, 3.3.3.3

代表请求由1.1.1.1发出,经过三层代理,第一层是2.2.2.2,第二层是3.3.3.3,而本次请求的来源IP4.4.4.4是第三层代理

X-Real-IP,没有相关标准,上面的例子,如果配置了X-Read-IP,可能会有两种情况

// 最后一跳是正向代理,可能会保留真实客户端IP
X-Real-IP: 1.1.1.1
// 最后一跳是反向代理,比如Nginx,一般会是与之直接连接的客户端IP
X-Real-IP: 3.3.3.3

所以 ,如果只有一层代理,这两个头的值就是一样的。

那一般在后端取值(比如 node.js 通过 nginx 代理)是用哪个值呢?我看 sf 上看一般推荐是用 X-Forwarded-For,直接用 X-Real-IP 岂不是更方便点?

X-Forwarded-For 确实是一般的做法

  1. 他在正向(如 squid)反向(如 nginx)代理中都是标准用法,而正向代理中是没有 x-real-ip 相关的标准的,也就是说,如果用户访问你的 nginx 反向代理之前,还经过了一层正向代理,你即使在 nginx 中配置了 x-real-ip,取到的也只是正向代理的 IP 而不是客户端真实 IP

  2. 大部分 nginx 反向代理配置文章中都没有推荐加上 x-real-ip ,而只有 x-forwarded-for,因此更通用的做法自然是取 x-forwarded-for

  3. 多级代理很少见,只有一级代理的情况下二者是等效的

  4. 如果有多级代理,x-forwarded-for 效果是大于 x-real-ip 的,可以记录完整的代理链路


1、将以下代码保存为 Client.php

// php 脚本开始
$ch = curl_init();
$url = "http://localhost/ser.php";
$header = array('CLIENT-IP:208.165.188.175', 'X-FORWARDED-FOR:208.165.188.175');
// 声明伪造 head 请求头
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,true);
$page_content = curl_exec($ch); curl_close($ch);
echo $page_content;


2、将以下代码保存为 ser.php

// php 脚本开始
echo getenv('HTTP_CLIENT_IP');
echo getenv('HTTP_X_FORWARDED_FOR');
echo getenv('REMOTE_ADDR');


测试结果为

208.165.188.175
208.165.188.175
127.0.0.1


上面结果可看出,http_client_ip、http_x_forwarded_for 都被伪造了,而 remote_addr 还是127.0.0.1 就是客户端 IP

总结:

如果我们没用到负载均衡(CDN)的话直接用 REMOTE_ADDR 获取 IP。

如果使用了一级 CDN 的话,CDN 会把 REMOTE_ADDR 转发成 X-Real-IP,我们服务器可以获取 X-Real-IP 来获取 IP 值。如果是多级 CDN 的话需要我们来做 nginx 代理,详细:https://www.cnblogs.com/princessd8251/articles/6268943.html

就是第一台负载服务器获取 REMOTE_ADDR 转发成 X-Real-IP,之后的去继承前一台的 X-Real-IP 就可以了,这里记住必须是去继承,不然第二台会把第一台的 REMOTE_ADDR 转发成 X-Real-IP 导致错误。

在 discuz! 中的获取 IP 的方法:

private function _get_client_ip() {
    $ip = $_SERVER['REMOTE_ADDR'];
    if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
        foreach ($matches[0] AS $xip) {
            if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
                $ip = $xip;
                break;
            }
        }
    }
    return $ip;
}

这里 DZ 为了符合有些用户会用代理,所以才首先使用了两个容易伪造的方法,如果有需要可以自行修改。

h
转自 hykeda 6 年前
6,575

场景:每天带笔记本电脑上班,公司使用固定 IP 上网,家里网络的网段又跟公司不一样。


方法 1:两个网络环境分别使用有线连接和无线连接(鉴于笔记本无线网卡不支持 5G(802.11ac),或者有其它需求必须都使用有线连接的不适用此方法)。

方法 2:修改家里路由器的局域网 IP 地址,使其网段与公司相同(虽然仅需要一次修改,但部分路由器不允许修改局域网 IP 地址);

方法 3:使用第三方软件一键切换(有安全隐患,且可能导致电脑网络设置出现错误);

方法 4(推荐):设置电脑网络连接同时使用两个 IP,具体方法如下:


打开“以太网 属性”,双击“Internet 协议版本 4 (TCP/IPv4)”,配置其中一个网络环境的 IP 地址和网关(例如我在公司上网的 IP 是 192.168.1.5,网关是 192.168.1.1)

image.png

点击“高级”,在 IP 地址栏添加另一个网络的 IP(如 192.168.31.5),在“默认网关”处添加这个网络的网关(如 192.168.31.1)

image.png

这样设置后,不管到公司还是回到家,只要网线一插就能上网,不需要每天更换 IP 地址设置了。

image.png

(图中显示了两个网络名称)

xoyozo 6 年前
6,776

新项目上线,在 Windows XP 中使用 IE 访问网站,http 正常, https 提示“无法显示网页”,这是因为当前电脑不支持网站提供的 SSL 协议。遂简单整理了各 IE 版本在不同操作系统下 SSL/TLS 的支持情况,表格仅供参考,可能会因特殊情况而有所不同:


SSL 2.0SSL 3.0TLS 1.0TLS 1.1TLS 1.2TLS 1.3
XP - IE6默认支持默认支持可选支持不支持不支持不支持
XP - IE8可选支持默认支持默认支持不支持不支持不支持
Vista - IE7可选支持默认支持默认支持不支持不支持不支持
Vista - IE9可选支持默认支持默认支持不支持不支持不支持
Win7 - IE8可选支持默认支持默认支持可选支持可选支持不支持
Win7 - IE11可选支持可选支持默认支持默认支持默认支持不支持
Win8 - IE10可选支持默认支持默认支持可选支持可选支持不支持
Win8.1 - IE11可选支持默认支持默认支持默认支持默认支持不支持
Win10 早期 - IE11 / Edge不支持可选支持默认支持默认支持默认支持不支持
Win10 - IE11 / Edge不支持可选支持

默认支持

(部分版本 可选支持

默认支持

(部分版本 可选支持

默认支持可选支持

几个注意点:

  • 宝塔面板(5.9.0)不支持 SSL 3.0 和 TLS 1.0,官方说已经恢复了 TLS 1.0 的支持,但我在 ssl_protocols 中添加 TLSv1 仍然不生效。后参考此文配置成功(同时更改 ssl_protocols 和 ssl_ciphers 项)

  • 详细的支持请前往 MySSL.com 检测,“客户端握手模拟”小节中查看各操作系统和浏览器版本的测试结果

xoyozo 6 年前
11,072

请求被中止: 未能创建 SSL/TLS 安全通道。

The request was aborted: Could not create SSL/TLS secure channel.

基础连接已经关闭: 发送时发生错误。

出现这个异常原因是请求的 SSL/TLS 版本与对方支持的不一致。

加上这段代码可解决:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Tls12 表示请求的安全协议是 TLS 1.2,您可以断点查看原来的 ServicePointManager.SecurityProtocol 值,只要设置为对方网站支持的版本即可。

使用下面这个工具可以查看对方网站提供的 SSL/TLS 版本:

https://myssl.com/

xoyozo 6 年前
7,473

〓 系统

功能命令--help示例
关机halt
halt
重启reboot
reboot
系统监视器top系统时间, 运行天数, 当前登录用户数, 系统负载
总进程数, 运行中的, 睡眠的, 停止的, 未响应的
Cpu(s):us 用户, sy 系统, ni XX, id 空闲, wa 等待, hi XX, si XX
Mem, 已使用, 空余, 缓冲
Swap, 已使用, 空余, 缓冲
快捷键:
M 按占内存排序
P 按占Cpu排序
1 显示每个 Cpu
k 杀死进程
q 退出
top
查看进程psaux
-ef
列出包含 java 的进程
ps aux |grep java 
ps -ef |grep java
查看内存及 Swap 用量free-b,-k,-m,-g 按单位显示free -m
查看系统时间date   显示 CST 时间
-R 显示时区
-u 显示 UTC 时间
date
查看硬件时间clock
clock
设置系统日期

date -s 月/日/年
设置系统时间

date -s 时:分:秒
将系统时间写入到硬件时间

clock -w
查看系统版本

cat /etc/*release
升级系统软件

yum update -y

〓 文件

功能命令--help示例
进入目录cd
cd .. # 上一层目录
cd /root # 根目录
列出目录ls白色:表示普通文件
蓝色:表示目录
绿色:表示可执行文件
红色:表示压缩文件
浅蓝色:链接文件
红色闪烁:表示链接的文件有问题
黄色:表示设备文件
灰色:表示其他文件
ls
创建目录mkdir
mkdir XXX
删除目录rm
rm -rf XXX
删除文件rm
rm XXX
复制文件cp
cp XXX YYY
复制目录cp-r 复制目录及目录内的所有项目
-v 详细显示进行的步骤
cp -rv XXX YYY
重命名文件mv-i: 若指定目录已有同名文件,则先询问是否覆盖旧文件;
-f: 在mv操作要覆盖某已有的目标文件时不给任何指示;
mv 源文件 目标文件
移动文件mvmv 一个或多个文件 目标目录
下载文件wget下载到当前目录wget http://XXX.tar.gz
计算文件/目录的磁盘用量du-a 不仅显示目录,同时显示文件
-h 容易阅读方式显示
--max-depth=N 可指定计算深度
du -ah --max-depth=1 | sort -n
查找文件find
find /home -name *.apk

〓 tar

功能命令--help示例
tartar-z 是否压缩
-c 打包
-x 解包
-v 详细地列出处理的文件
-f 
打包:tar -cvf abc.tar abc
解包:tar -xvf abc.tar
压缩打包:tar -zcvf abc.tar.gz abc
解压解包:tar -zxvf abc.tar.gz

〓 磁盘

功能命令--help示例
查看所有磁盘及分区fdisk -l
fdisk -l
查看当前挂载df-h 按可阅读的方式打印数值和单位
-T 显示文件系统类型
df -hT
管理磁盘分区fdisk /dev/***进入后的操作说明:
m 显示命令菜单
d 删除一个分区
n 创建一个分区(e 扩展分区;p 主分区)
t 改变分区ID
q 不保存退出
w 保存退出
fdisk /dev/vdb
格式化分区mkfs.*** /dev/***N
mkfs.xfs /dev/vdb1
挂载分区mount /dev/***N /***
mount /dev/vdb1 /www
卸载分区umount /dev/***N
umount /dev/vdb1
开机自动挂载vi /etc/fstab配置文档格式:设备 挂载点 文件系统类型 defaults 0 0打开:vi /etc/fstab
配置:/dev/vdb1 /www xfs defaults 0 0

〓 网络

功能命令--help示例
查看 IP 配置ifconfig
ifconfig
配置网卡 IP
配置文件目录:/etc/sysconfig/network-scripts/
配置文件格式:
DEVICE=eth0 / eth0:0 / ... # 在配置多线时若使用 cp 命令复制配置文件,必须修改此项以防止冲突
HWADDR=XX:XX:XX:XX:XX:XX # 网卡地址
TYPE=Ethernet # 以太网
UUID=********
ONBOOT=yes # 开机启动
NM_CONTROLLED=yes
BOOTPROTO=static # 使用静态 IP
IPADDR=192.168.1.2 # IP 地址
NETMASK=255.255.255.XXX # 子网掩码
GATEWAY=192.168.1.1 # 网关
DNS1=114.114.114.114
DNS2=8.8.8.8
vi ifcfg-XXXN(:N)
重启网卡
使配置生效service network restart

〓 防火墙

功能命令--help示例
配置 iptables
添加需要允许的端口的方法同 22 端口vi /etc/sysconfig/iptables
重启使配置生效

service iptables restart

〓 用户/权限

功能命令--help示例
添加用户useradd-g 组名 # 加入到该组
-s /bin/false #不允用户直接登录系统
useradd –g 组名 用户名 -s /bin/false
修改密码passwd
passwd 用户
查看所有用户

cut -d : -f 1 /etc/passwd 
查看可以登录系统的用户

cat /etc/passwd | grep -v /sbin/nologin | cut -d : -f 1
删除用户
-r, --remove                  remove home directory and mail spooluserdel 用户
添加用户组groupadd
groupadd 组名
为组添加用户(用户必须已存在)gpasswd
gpasswd -a 用户 组
将用户移出组gpasswd
gpasswd -d 用户 组
查看用户所属组groups
groups 用户
查看组中有哪些用户groupmems
groupmems -g 组 -l
更改文件/目录所有者chown-R 递归处理所有的文件及子目录chown -R 用户:组 ***
更改文件/目录权限chmod-R 以递归方式更改所有的文件及子目录chmod -R 777 ***

〓 vi 编辑器

功能命令--help示例
打开文件vi
vi XXX
进入编辑模式
按 a/i/o/Insert 等
进入末行模式/命令模式
按 Esc后:
:w 保存不退出
:q 退出(提示是否保存)
:wq 保存并退出
:w XXX 另存到文件 XXX
:q! 不保存退出

〓 计划任务

功能命令--help示例
设置计划任务crontab详细步骤见本页底部crontab -l # 查看计划任务
crontab -e # 编辑计划任务

〓 网站

功能命令--help示例
简单审查日志cat | grep
cat 日志文件 | grep 关键词1 | grep 关键词2 | more
日志分析goaccess
见下文

〓 goaccess

功能命令--help示例
安装yum install goaccess

日志格式NCSA Commbined Log Format
date_format %d/%b/%Y
log_format %h %^[%d:%^] "%r" %s %b "%R" "%u"
参数-f需要解析的日志文件
参数-e指定 IP 地址统计
参数-p指定配置文件可以将上面的日志格式内容保存到文件 ~/.goacessrc
参数-H显示 HTTP 协议信息
参数-M显示 HTTP 方法信息
生成文件

goaccess -f 日志文件 -p ~/.goaccessrc > 目标文件.htm

〓 lnmp

功能命令--help示例
重启 LNMP

/root/lnmp restart
重启 MySQL

/etc/init.d/mysql restart
重启 PureFTPd

/root/pureftpd restart
安装 LNMP
http://lnmp.org/install.html 
常见问题
http://lnmp.org/faq.html 
状态管理命令
http://lnmp.org/faq/lnmp-status-manager.html 
相关软件目录及文件位置
http://lnmp.org/faq/lnmp-software-list.html 
防跨站、跨目录安全设置(仅支持 PHP 5.3.3 以上版本)
http://www.vpser.net/security/lnmp-cross-site-corss-dir-security.html 
查看 Nginx 版本

nginx -V
查看 MySQL 版本

mysql -V
查看 PNP 版本

php -v
查看 Apache 版本

httpd -v
查内存

cat /proc/meminfo
php.ini

vim /usr/local/php/etc/php.ini
MySQL 配置文件

vim /etc/my.cnf
添加网站

/root/vhost.sh
添加 ProFTPd 用户

/root/proftpd_vhost.sh

〓 nginx

功能命令--help示例
启动/停止/重启service nginx

/etc/rc.d/init.d/nginx

service nginx start
service nginx stop
service nginx restart
伪静态在 .conf 文件中配置
rewrite ^(.*)/read-htm-(.*)\.html(.*)$ $1/read.php?$2.html? last;
rewrite ^(.*)/thread-htm-(.*)\.html(.*)$ $1/thread.php?$2.html? last;
rewrite ^(.*)-htm-(.*)$ $1.php?$2 last;
rewrite ^(.*)/simple/([a-z0-9\_]+\.html)$ $1/simple/index.php?$2 last;
rewrite ^(.*)/data/(.*)\.(htm|php)$ 404.html last;
rewrite ^(.*)/attachment/(.*)\.(htm|php)$ 404.html last;
rewrite ^(.*)/html/(.*)\.(htm|php)$ 404.html last;
防盗链在 .conf 文件中配置HttpRefererModule location ~* \.(gif|jpg|png|swf|flv)$
{
valid_referers none blocked *.0574bbs.com *.eyuyao.com 0574bbs.com eyuyao.com;
if ($invalid_referer)
{
rewrite ^/ http://web1.eyuyao.com/yyad/src/3122.jpg;
# return 404;
}
}
浏览器缓存在 .conf 文件中配置
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}

〓 vsftpd

功能命令--help示例
安装

yum install vsftpd
查看是否已安装

rpm -q vsftpd
启动/停止/重启service vsftpd
service vsftpd start
service vsftpd stop
service vsftpd restart
配置文件

vi /etc/vsftpd/vsftpd.conf

〓 MySQL

功能命令--help示例
登录mysql
mysql -u username -p
登出

exit
查看信息

status;
查询当前正在执行的 SQL 语句

show processlist;
删除指定时间之前的日志PURGE
PURGE MASTER LOGS BEFORE '2015-1-1 0:00:00';

〓 scp 远程文件/目录传输命令 (yum install openssh-clients) 用法

scp 会把文件权限(读取/写入/执行)带过来,但所有者为当前执行 scp 命令的用户。

scp 低版本有许多漏洞,用完最好 yum remove openssh-clients

scp 采用直接覆盖的机制,如需判断文件无差异则跳过,应改用 rsync 命令。查看 rsync 详细使用方式及与 scp 对比

功能命令--help示例
若远程服务器 SSH 端口非默认scp-P 端口号
下载远程服务器上的文件到本地scp
scp 远程用户@远程服务器:远程文件 本地文件
下载远程服务器上的目录到本地scp

-P 端口

-v 显示进度

-r 递归

scp -r 远程用户@远程服务器:远程目录 本地目录

实例:scp -r root@x.x.x.x:/a/b/ /c/d/

结果:/c/d/b/,即将整个 b 复制到 d 下(注意与 rsync 命令的区别)


本地文件上传到远程服务器scp
scp 本地文件 远程用户@远程服务器:远程文件
本地目录上传到远程服务器scp最终目录结构参:远程->本地scp -r 本地目录 远程用户@远程服务器:远程目录

〓 rsync 远程文件/目录传输命令 (yum install rsync) 用法查看 rsync 详细使用方式及与 scp 对比

rsync 会把文件权限(读取/写入/执行)带过来,所有者也会带过来。

相比于 scp 最大的优势就是可以增量同步

功能命令--help示例
下载远程服务器上的目录到本地rsync

-a 递归

-v 详细

-p, -- perms 保持权限

-g, -- group 保持属组

-o, --owner 保持属主

-r 递归

--progress 打印

--delete 删除已不存在的文件

-u 表示仅更新较新的文件

-z 表示在传输过程中进行压缩

-e 'ssh -p 2222' 指定其它端口

rsync 远程用户@远程服务器:远程目录 本地目录

实例:rsync -avu --progress root@x.x.x.x:/a/b/ /c/d/

结果:/c/d/,即将 b 内的文件(夹)复制到 d 下(注意与 scp 命令的区别)


本地文件上传到远程服务器rsync
rsync 本地文件 远程用户@远程服务器:远程文件
本地目录上传到远程服务器rsync最终目录结构参:远程->本地rsync 本地目录 远程用户@远程服务器:远程目录

〓 ftp 客户端 (yum install ftp)

功能命令--help示例
登录ftp
ftp 目标服务器
列出远程当前路径目录/文件ls
ls
创建远程目录mkdir
mkdir 目录名
删除远程目录(空)rmrmdir
mkdir 目录名
进入远程目录cd
cd 目录名
显示远程当前路径pwd
pwd
重命名远程文件rename
rename 原文件名 新文件名
上传文件put
put 本地文件名
下载文件get
get 远程文件名
批量下载文件mget需要单个确认
批量下载文件【lftp】mirror参数有很多mirror
返回 shell(不退出)!
!
返回 ftp(接上步)exit
ftp

exit
ftp
结束bye
quit

bye
quit

〓 iftop

流量监控工具 教程 

〓 GoAccess

实时网站日志分析工具 官网 

〓 Cacti

网络流量监测图形分析工具 官网  百科 

常见问题笔记

加硬盘

  • 插入新硬盘

  • 若有 RAID,则先设置,使操作系统能认到硬盘

  • 使用 fdisk 命令对新设备进行分区

  • 使用 mkfs 命令对新分区进行格式化

  • 使用 mount 命令进行挂载

  • 设置开机自动挂载(vi /etc/fstab)

更改 MySQL 数据库目录位置

  • 停止 MySQL 服务

  • 将原数据目录转移或复制到新位置(若是复制,则修改所有者使原来一致)

  • 找到 my.cnf 配置文件(一般在 /etc/),修改 datadir 值为新路径

  • 启动 MySQL 服务

502 Bad Gateway 问题排查

  • 查看 PHP 日志,路径:/usr/local/php/var/log

  • 一般为“server reached pm.max_children setting (10), consider raising it”连接数问题,在“/usr/local/php/etc”下的所有配置文件中查找并修改相关设置即可(如改成 1000)。

计划任务(实例:定时备份数据库并通过 FTP 同步至其它服务器)

  • 创建可执行文件:vi dotask.sh

  • dotask.sh 的内容示例:

    DATE_TIME=`date +%Y_%m_%d_%H%M%S`;
    FILE_NAME=数据库名_backup_$DATE_TIME.sql;
    cd /home/mysqlbackup/;
    mysqldump -u数据库用户名 -p数据库密码 数据库名>$FILE_NAME;
    tar -zcf $FILE_NAME.tar.gz $FILE_NAME;
    rm $FILE_NAME;

    ftp -v -n FTP地址 << END
    user FTP用户名 FTP密码
    bin
    put 本地目录文件 目标路径文件
    bye
    END


    文件名乱码问题可以在行末加“;”来解决

  • 赋予执行权限:chmod 777 dotask.sh (ls 命令时呈绿色)

  • 编辑计划任务:crontab -e

  • crontab 书写规则:

    # 分 时 日 月 周 文件路径
    0 3 * * * /home/dotask.sh
    30 4 * * * /home/dotask2.sh


    更多帮助 

  • 重启 crond:/etc/init.d/crond restart

netstat

  • netstat -an | grep xxx.xxx.xxx.xxx 可查看此 IP 的 TCP 请求及端口

xoyozo 6 年前
6,182

安装过程就不介绍了,主要记一下被动模式和端口开放设置。


FileZilla Server 默认以 21 端口安装,阿里云的安全组配置“入方向”规则:

协议类型:自定义 TCP,端口范围:21/21,授权对象 0.0.0.0/0


如果要配置“被动模式”,那么在 FileZilla Server 菜单中选择“Edit”- Settings

切换到“Passive mode settings”,打勾“Use custom port range”,并填写端口范围,譬如 30000-40000,确定。


同样在阿里云安全组中配置“入方向”规则:

协议类型:自定义 TCP,端口范围:30000/40000,授权对象 0.0.0.0/0


这样就可以使用被动模式连接了。

如果无法连接,可尝试打开 Windows Server 2016 的“服务器管理器”,选择右上角“工具”-“高级安全 Windows 防火墙”-“入站规则”-“新建规则”,将上述端口设为允许连接。

xoyozo 7 年前
6,598