May19

【原创】阿里云VPC网络下频繁TCP Retransmission故障排查

Author: leeon  Click: 500   Comments: 0 Category: 网络  Tag: aliyun,tcp,retransmission,vpc

最近将一个业务迁移到阿里云VPC虚拟专网下,但是迁移后发现从公司网络下访问阿里云的80端口业务频繁出现连接不通的问题,抓包发现存在大量从公司IP到阿里云虚拟专网IP的TCP Retransmission出现。


从图中可以看到从我们办公网络访问80端口大量SYN重传,这也就是说在三次握手的第一步中就被重传了。换言之在主动发起SYN后如果没有收到服务器放的ACK确认,就会导致重传的发生,因为客户端机器认为远程机器没有收到包,而发生重新发送SYN包的事件。

既然在服务器上抓包能捕获SYN的请求,那就说明服务器端接收到了请求但是没有回应ACK包,于是想起了以前nat环境下tw_recyle的坑,当多个客户端使用同一个外网IP通过NAT访问内网服务器的时候,服务器如果在内核参数中打开了net.ipv4.tcp_tw_recycle = 1

就有可能导致服务器收到SYN但是不会向客户端发送SYN+ACK包。因为打开recyle参数后会识别这些包的时间戳(net.ipv4.tcp_timestamps = 1),但是nat过来的数据包又因为时间戳有可能不是顺序的,导致服务器认为包不可信而丢弃。

故当我们在使用阿里云的VPC虚拟专网的时候,使用弹性IP接入,一定要注意NAT的问题,在服务器参数上关闭net.ipv4.tcp_tw_recycle。 否则从一个ip来的不同客户端请求很有可能导致大量请求失败

Feb4

【原创】在树莓派3上给Nginx部署免费HTTPS证书

Author: leeon  Click: 786   Comments: 0 Category: 网络  Tag: https,nginx,certbot,ssl

    自从家里的电信ADSL好几年前封锁80端口后,http服务已经不能用来作为公网服务直接访问了,但是电信对443端口并没有屏蔽,我们可以通过配置https服务来提供公网服务。最近炒的火热的Let's Encrypt免费CA服务提供商,刚好趁着苹果强制ATS的东风横空出世,得益于Mozilla的支持将免费SSL证书全民普及的概念广而告之,自从去年沃通的免费证书关停等等一系列免费的ssl证书被停止服务,这证书刚好拿来耍耍,体验一下。

   使用Let's Encrypt的免费ssl需要安装官方提供的certbot脚本,这个脚本需要安装树莓派的backports源,我们需要增加对backports源的支持。

修改/et/apt/sources.list文件,在末尾添加

deb http://ftp.debian.org/debian/ jessie-backports main contrib non-free

然后还需要安装debian-keyring,debian-archive-keyring 两个包才能正常,否则在添加backports源后会提示

W: GPG error: http://ftp.debian.org jessie-backports InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553 NO_PUBKEY 7638D0442B90D010


执行如上步骤后,最后执行一次apt update来更新源。

接着我们就可以按照官方提供的文档进行操作了。

[code="bash"]
$ sudo apt-get install certbot -t jessie-backports
[/code]

安装certbot工具包成功后,如果想单独生成ssl证书,使用standalone模式即可。certbot也提供了几种不同的生成模式:

Plugin Auth Inst Notes Challenge types (and port)
apache Y Y
Automates obtaining and installing a cert with Apache 2.4 on
Debian-based distributions with libaugeas0 1.0+.
tls-sni-01 (443)
webroot Y N
Obtains a cert by writing to the webroot directory of an
already running webserver.
http-01 (80)
nginx Y Y
Automates obtaining and installing a cert with Nginx. Alpha
release shipped with Certbot 0.9.0.
tls-sni-01 (443)
standalone Y N
Uses a “standalone” webserver to obtain a cert. Requires
port 80 or 443 to be available. This is useful on systems
with no webserver, or when direct integration with the local
webserver is not supported or not desired.
http-01 (80) or tls-sni-01 (443)
manual Y N
Helps you obtain a cert by giving you instructions to perform
domain validation yourself.
http-01 (80) or dns-01 (53)
certbot生成的证书会存在在/etc/letsencrypt/live/(设置证书时绑定的域名目录)下。Let’s Encrypt CA证书仅提供90天有效期,故在此过期时间之前需要定期重新生成一次证书。

在执行certbot renew命令时候程序会自动判断是否过期,但我们可以通过添加--dry-run命令来模拟生成新证书。

如果需要强制重新生成证书则添加 --force-renewal参数执行,但请不要频繁的重新生成证书,这样会受到请求频率限制。

certbot成功生成的文件有四个:

cert.pem 主要针对Apache<2.4.8版本的证书文件

chain.pem 主要针对Apache<2.4.8版本的证书文件

fullchain.pem 证书文件,对应nginx中的ssl_certificate 参数配置,对应Apache >= 2.4.8配置中的SSLCertificateFile参数

privkey.pem 证书的私钥文件,对应nginx配置中的ssl_certificate_key 参数配置 ,对应apache配置中SSLCertificateKeyFile参数

Mar18

【原创】使用pcap.net在windows下实现自定义的抓包分析工具

Author: leeon  Click: 7434   Comments: 4 Category: 网络  Tag: winpcap,csharp,pcapdotnet

      最近需要在windows平台下通过抓包分析工具把http的GET请求地址抓出来,其实在很多应用场景下我们都需要这样类似的工具,比如httpwatch,fiddler,chrome,firefox下的开发者工具,这些都必须绑定到浏览器才能使用,如果我们需要一个可以自定义的抓包分析工具来分析这些http get和post请求,那么我们该怎么做呢? 搜索了一番有python在windows下抓包分析的实现,也有c++原生使用winpcap库来使用,python的兼容性不好不方便部署使用,c++的开发难度系数较大,维护成本较高,最后发现有国外有人介绍说winpcap在c#的封装实现不错,果断去官方网站 http://pcapdotnet.codeplex.com/ 下载了开发包来学习。

     官方文档说要装.net framework 4.0 和winpcap 4.1.2 其实在自己的开发环境中我选用的是.net framework 4.5版本和winpcap 4.1.3 都是可以兼容的。下载的开发包中已经涵盖了官网上介绍的一些示例代码。只要在vs中打开工程进行编译生成就好了。

    鉴于官方网站上示例代码非常有限,而且提供的api手册比较粗糙,导致撸主在官网论坛查阅了很长时间那陈旧的帖子内容才得到一些启示。撸主想实现的功能非常简单,就是想不通过浏览器附带的http抓包工具来实现底层的http抓包过滤,例如wireshark中的过滤规则一样可以把我所访问的所有http请求都过滤出来。这样我们只要启用这个小工具,就可以在底层上实现透明抓包,任何通过本机网卡访问的http请求都不会被放过! 废话不多说,放上实现代码:

[code="plain"]
using System;
using System.Collections.Generic;
using PcapDotNet.Core;
using PcapDotNet.Packets;
using PcapDotNet.Packets.IpV4;
using PcapDotNet.Packets.Transport;
using PcapDotNet.Packets.Http;
using System.Text;

namespace InterpretingThePackets
{
class Program
{
static void Main(string[] args)
{
// Retrieve the device list from the local machine
IList allDevices = LivePacketDevice.AllLocalMachine;

if (allDevices.Count == 0)
{
Console.WriteLine("No interfaces found! Make sure WinPcap is installed.");
return;
}

// Print the list
for (int i = 0; i != allDevices.Count; ++i)
{
LivePacketDevice device = allDevices[i];
Console.Write((i + 1) + ". " + device.Name);
if (device.Description != null)
Console.WriteLine(" (" + device.Description + ")");
else
Console.WriteLine(" (No description available)");
}

int deviceIndex = 0;
do
{
Console.WriteLine("Enter the interface number (1-" + allDevices.Count + "):");
string deviceIndexString = Console.ReadLine();
if (!int.TryParse(deviceIndexString, out deviceIndex) ||
deviceIndex < 1 || deviceIndex > allDevices.Count)
{
deviceIndex = 0;
}
} while (deviceIndex == 0);

// Take the selected adapter
PacketDevice selectedDevice = allDevices[deviceIndex - 1];

// Open the device
using (PacketCommunicator communicator =
selectedDevice.Open(65536, // portion of the packet to capture
// 65536 guarantees that the whole packet will be captured on all the link layers
PacketDeviceOpenAttributes.Promiscuous, // promiscuous mode
1000)) // read timeout
{
// Check the link layer. We support only Ethernet for simplicity.
if (communicator.DataLink.Kind != DataLinkKind.Ethernet)
{
Console.WriteLine("This program works only on Ethernet networks.");
return;
}

// Compile the filter
using (BerkeleyPacketFilter filter = communicator.CreateFilter("ip and tcp and dst port 80"))
{
// Set the filter
communicator.SetFilter(filter);
}

Console.WriteLine("Listening on " + selectedDevice.Description + "...");

// start the capture
communicator.ReceivePackets(0, PacketHandler);
}
}

// Callback function invoked by libpcap for every incoming packet
private static void PacketHandler(Packet packet)
{
if (packet == null) { return; }
if (packet.Ethernet == null) { return; }
if (packet.Ethernet.IpV4 == null) { return; }
if (packet.Ethernet.IpV4.Tcp == null) { return; }
if (packet.Ethernet.IpV4.Tcp.Http == null) { return; }
try
{
HttpDatagram http = packet.Ethernet.IpV4.Tcp.Http;

if (http.IsRequest && http.IsValid) {
String msg = http.Decode(Encoding.UTF8).Split('\n')[0];
if (msg.StartsWith("GET ") || msg.StartsWith("POST "))
{
Console.WriteLine(msg);
}
}
}
catch (Exception e)
{

}
}
}
}
[/code]


这里的实现是过滤出访问远端服务器80端口的tcp请求报文,同时截取http头部是get或者post开头的单行字符串。这样我们就可以捕获所有http协议访问的url了。

Mar20

IE Firefox 在进行某些跳转时请求头中不会附加 Referer 字段信息

Author: w3help.org  Click: 12978   Comments: 2 Category: 网络  Tag: refer,http

标准参考

根据 HTTP1.1 规范中的描述,请求头中的 Referer 字段允许用户端为服务端指定得到的请求 URI 的资源地址 (URI),允许服务端生成资源的反向链接列表,同时也允许追踪维护过时的或者是拼写错误的链接。若一个请求 URI 获得自一个没有自身 URI 的源,则该请求 URI 的 Referer 字段不得被发送,如来自用户键盘的输入。

  Referer = "Referer" ":" ( absoluteURI | relativeURI )

如:Referer: http://www.w3.org/hypertext/DataSources/Overview.html

关于 Referer 的更多信息,请参考 Hypertext Transfer Protocol -- HTTP/1.1 规范 14.36 Referer 中的内容。

问题描述

IE6 IE7 IE8 始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中。在普通页面中,当脚本调用 location 对象进行跳转时也不会附加 Referer 字段信息;
Firefox 始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中。

造成的影响

若服务端依靠请求头中的 Referer 字段信息进行某些操作,则在使用 META 元素进行页面跳转以及脚本 location 对象进行跳转时在某些浏览器中由于无 Referer 字段而产生差异。

受影响的浏览器

IE6 IE7 IE8  
Firefox  

问题分析

创建一个 Web 服务器,如 Apache。在服务器上编写一段动态代码,用于输出接收到的请求头的 Referer 字段信息。如:refer.php

<?php
  echo '<style>* { font:12px "Trebuchet MS"; }</style>';
  echo (isset($_SERVER['HTTP_REFERER'])) ? 'Referer: ' . $_SERVER['HTTP_REFERER'] : 'Referer: N/A';
?>

本文中将测试 5 种常见的跳转方式,并分别在普通页面及 IFRAME 框架页内测试这些跳转方式下请求头 Referer 字段的发送情况。

5 种跳转方式代码:

anchor.html
<a href="refer.php">Anchor</a>
form_submit.html
<body>
<form action="refer.php"><input type="submit" /></form>
<script>
  document.forms[0].submit();
</script>
</body>
meta.html
<meta http-equiv="refresh" content="1;url=refer.php">
http302.php
<?php
  header('Location: refer.php');
?>
location.html
<script>location.href="refer.php";</script>

测试页面:

index.html
<!DOCTYPE html>
<html>
<head>
<base target="_blank" />
<style>
  * { margin:0; font:16px 'Trebuchet MS'; }
</style>
</head>
<body>
<a href="anchor.html">Anchor</a><br />
<a href="form_submit.html">Form submit</a><br />
<a href="meta.html">META</a><br />
<a href="302.php">HTTP 302</a><br />
<a href="location.html">location.href</a>
</body>
</html>
iframe.html
<!DOCTYPE html>
<html>
<head>
<style>
  * { margin:0; font:16px 'Trebuchet MS'; }
  iframe { width:400px; height:40px; display:block; }
</style>
</head>
<body>
<h1>Anchor:</h1>
<iframe id="anchor" name="anchor" scrolling="no" frameborder="0" src="anchor.html"></iframe>
<h1>Form submit:</h1>
<iframe id="form_submit" name="form_submit" scrolling="no" frameborder="0" src="form_submit.html"></iframe>
<h1>META:</h1>
<iframe id="meta" name="meta" scrolling="no" frameborder="0" src="meta.html"></iframe>
<h1>HTTP 302:</h1>
<iframe id="http302" name="http302" scrolling="no" frameborder="0" src="302.php"></iframe>
<h1>location.href:</h1>
<iframe id="loc" name="loc" scrolling="no" frameborder="0" src="location.html"></iframe>
</body>
</html>

在各浏览器中分别打开上表的 "index.html"、"iframe.html",对于页面 "anchor.html" 需要用户手动点击超链接。

这段代码在不同的浏览器环境中的表现:

  IE6 IE7 IE8 Firefox Chrome Safari Opera
index.html 普通超链接 anchor.html OK OK OK
表单提交 form_submit.html OK OK OK
META 跳转 meta.html Fail Fail OK
HTTP 302 跳转 302.php OK OK OK
脚本 location.href 跳转 location.php Fail OK OK
iframe.html 普通超链接 anchor.html OK OK OK
表单提交 form_submit.html OK OK OK
META 跳转 meta.html Fail Fail OK
HTTP 302 跳转 302.php OK OK OK
脚本 location.href 跳转 location.php OK OK OK

可见,对于普通超链接、表单提交、302 跳转,各浏览器均会在请求头附加 Referer 字段信息,而对于 META 元素控制跳转及通过脚本使用 location 对象进行跳转时:

  •  IE6 IE7 IE8 中,始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中。在普通页面中,当脚本调用 location 对象进行跳转时也不会附加 Referer 字段信息;

  •  Firefox 中,始终不在使用 META 元素控制跳转时附加 Referer 字段到请求头中;
  •  Chrome Safari Opera 中,则对于测试的 5 种方式下均会附加 Referer 字段信息。

解决方案

若服务端需要获得正确的 Referer 字段信息,则应采用各浏览器均可以附加 Referer 字段信息的方式进行跳转。如,普通超链接、表单提交、HTTP 302 跳转。

分类

标签

归档

最新评论

ligaofeng在11:55:22评论了
file_get_contents超时问题的解决方法
我也不知道叫个啥好在00:59:46评论了
shell中使用while循环ssh的注意事项
司马成空在16:14:13评论了
【原创】ZendStudio中格式化HTML代码错位问题修正
Owen在22:56:46评论了
【原创】MyBatis Generator使用小记
waltye在23:38:05评论了
【原创】武汉互联网公司介绍[2016年8月更新版]

我看过的书

链接

其他

访问本站种子 本站平均热度:6010 c° 本站链接数:27 个 本站标签数:428 个 本站被评论次数:87 次