用代理自动配置文件PAC给iPhone和iPad设备添加socks代理

iOS实际上支持socks代理的,但在 iPhone和iPad设备的

Setting -> WLAN 下只能看到HTTP Proxy

HTTP Prxoy有3种模式: 关闭Off/手动Manual/自动Auto

用自动配置文件,就可以支持socks代理

1
2
3
4
function FindProxyForURL(url, host)
{
     return "SOCKS proxy_host:proxy_port";
}

将上面的proxy_host和proxy_port换成socks服务器实际的IP地址和端口
然后保存为 proxy.pac
放到 http://you_http_server/proxy.pac

在 iPhone设备中,添加自动配置 URL 为上面的地址,就可以使用socks代理了

扩展1:
局域网流量不要用代理

1
2
3
4
5
6
7
function FindProxyForURL(url, host)
{
    if (isInNet(host, "192.168.1.0", "255.255.255.0"))
        return "DIRECT";
 
    return "SOCKS proxy_host:proxy_port";
}

参考资料  代理自动配置(Proxy Auto Config)

一个PAC文件包含一个JavaScript的函数”FindProxyForURL(url, host)”. 这个函数返回一个包含一个或多个访问规则的字符串。用户代理根据这些规则适用一个特定的代理其或者直接访问。 当一个代理服务器无法响应的时候,多个访问规则提供了其他的后备访问方法。 浏览器在访问其他页面以前,首先访问这个PAC文件。PAC文件中的URL可能是手工配置的,也可能是是通过网页的网络代理自发现协议(Web Proxy Autodiscovery Protocol)自动配置的。

为了完整性和最佳的兼容性,我们应该设置网页服务器(apache或者nginx,lighttpd等等)将这个pac文件的MIME类型声明为 application/x-ns-proxy-autoconfig 或者 application/x-javascript-config
对于现代浏览器来说,两种mime类型都没有问题, 但 application/x-ns-proxy-autoconfig 相对 application/x-javascript-config 被更多的客户端所支持, 因为它被定义在最初的Netscape规范里

FindProxyForURL的返回值,可以是以下3种之一,或者是它们的组合

DIRECT
直接连接,不使用代理

PROXY host:port
   使用指定的http代理

SOCKS host:port
   使用指定的SOCKS代理
如果是多个组合,要用 分号;拼接起来
并且,放在最左边的优先级最高,如果最左边的失败,依次往右边尝试

如果最左边的代理服务器挂掉了,并且你在右边没有指定DIRECT选项, 浏览器应该会问你
代理服务器挂了,能不能临时忽略它,直接连接网络?

参考资料  PAC Functions (强烈推荐)
Navigator Proxy Auto-Config File Format (NetScape原始规范)
The Practical Proxy PAC file guid (最最强烈推荐)

shExpMatch(str, shexp)
第1个参数str, 待比较的任意字符串,一般是url或者host
第2个参数shexp是shell表达式,随意可以有*号通配符

isPlainHostName(host)
如果host是不含有”.”, 说明是一个主机名, 就返回true;
如果有点号,说明是一个域名, 返回false
host是从URL中分离出来的主机名(不包括端口号)

isInNet(host_or_ip, pattern, mask)
这个函数将会考察第1个参数 ip地址 (如果传入的参数是主机名,会被自动转换为ip地址)
看它是否在 第2个参数pattern 和 第3个参数 mask 决定的子网络范围内

例如

1
2
3
4
5
if (isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0"))
    return "DIRECT";
 
if (isInNet(myIpAddress(), "10.10.1.0", "255.255.255.0"))
    return "PROXY 10.10.5.1:8080";

其中myIpAddress() 返回 浏览器所在的主机的当前IP地址, 很多时候这是个局域网地址

dnsResolve(host) 将host解析为ip地址

1
2
3
4
5
6
var resolved_ip = dnsResolve(host);
if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
    isInNet(dnsResolve(host), "172.16.0.0""255.240.0.0") ||
    isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
    isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0"))
    return "DIRECT";

这段必须用上啊

dnsDomainIs(host, domain)

if (dnsDomainIs(host, “.google.com”))
return “DIRECT”;

其中host是从URL分离出来的主机名

localHostOrDomainIs(host, hostdom)

if (localHostOrDomainIs(host, “www.google.com”))
return “DIRECT”;

hostdom 是 域名全称
host 既可以是 域名,也可以是 简短主机名
如果是域名,必须完全同 hostdom 匹配
如果是主机名,必须同 hostdom的主机名 要完全匹配

isResolvable(host)

dnsResolve(host)

dnsDomainLevels(host)

dnsDomainLevels(“www”)

返回 0

dnsDomainLevels(“www.netscape.com”)
返回 2
调试是个大问题
PAC是一个javascript脚本,浏览器在每次请求一个URL之前,都会运行它.
但它和普通的js脚本有点不同

1)在PAC中,有个几个特殊的函数,它只能在PAC运行,在普通的js脚本运行会报告
“is not defined”
比如 shExpMatch

2)PAC的执行,也不支持js的所有特性.

3)在不同的浏览器中,对pac脚本的执行有着不同的实现方式.
可以用Firefox的错误控制台来查看错误信息
IE也支持alert()
并且 pac文件可以存在于本地文件系统
用 file:///var/run/x.pac 这样的路径
而不要用 http ,方便调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function FindProxyForURL(url, host)
   {
       if (isPlainHostName(host) || dnsDomainIs(host, ".mydomain.com"))
           return "DIRECT";
       else if (shExpMatch(host, "*.com"))
           return "PROXY proxy1.mydomain.com:8080; " +
                  "PROXY proxy4.mydomain.com:8080";
       else if (shExpMatch(host, "*.edu"))
           return "PROXY proxy2.mydomain.com:8080; " +
                  "PROXY proxy4.mydomain.com:8080";
       else
           return "PROXY proxy3.mydomain.com:8080; " +
                  "PROXY proxy4.mydomain.com:8080";
   }

我的最终版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function FindProxyForURL(url, host)
{
    url  = url.toLowerCase();
    host = host.toLowerCase();
 
    if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
        isInNet(dnsResolve(host), "172.16.0.0""255.240.0.0") ||
        isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
        isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0"))
        return "DIRECT";
 
    if (shExpMatch(url,"*twitter*")  ||
        shExpMatch(url,"*facebook*") ||
        shExpMatch(url,"*blogspot*") ||
        shExpMatch(url,"*youtube*") ||
       )
    {
       return "SOCKS 1.2.3.4:1080; DIRECT";
    }
}

Chrome在Linux下没有代理配置界面,但可以通过命令行参数配置

–proxy-server=host:port
–no-proxy-server
–proxy-auto-detect
–proxy-pac-url=URL

pac就用
–proxy-pac-url=file:///var/run/autoproxy.pac

新的浏览器支持正则表达式
如果需要做一些较为复杂的判断,那可直接抛弃 shExpMatch 函数,而自己使用正则表达式或别的工具来进行判断,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
var regexpr = /[a-zA-Z]{4}.microsoft.com/;
    if(regexpr.test(host))
        return "PROXY w3proxy:8080; DIRECT";
 
调试,使用alert,在IE上没问题
 
 
function isMatchProxy(url, pattern) {
    try {
        return new RegExp(pattern.replace('.', '.')).test(url);
    } catch (e) {
        return false;
    }
}
 
function FindProxyForURL(url, host) {
    debugPAC ="PAC Debug Informationn";
    debugPAC +="-----------------------------------n";
    debugPAC +="Machine IP: " + myIpAddress() + "n";
    debugPAC +="Hostname: " + host + "n";
    if (isResolvable(host)) {
        resolvableHost = "True"
    } else {
        resolvableHost = "False"
    };
    debugPAC += "Host Resolvable: " + resolvableHost + "n";
    debugPAC += "Hostname IP: " + dnsResolve(host) + "n";
    if (isPlainHostName(host)) {
        plainHost = "True"
    } else {
        plainHost = "False"
    };
    debugPAC += "Plain Hostname: " + plainHost + "n";
    debugPAC += "Domain Levels: " + dnsDomainLevels(host) + "n";
    debugPAC += "URL: " + url + "n";
    alert(debugPAC);
    var Proxy = 'SOCKS 1.2.3.4:9625; DIRECT';
 
    var list = [
        't.co',
        'twitter.com',
        'twimg.com',
        'posterous.com',
        'tinypic.com',
        'twitpic.com',
        'bitly.com',
        'yfrog.com',
        'youtube.com',
        'facebook.com',
        'appspot.com',
        'dropbox.com',
        'flickr.com',
        'youtube.com',
        'ytimg.com',
        'plus.google.com',
        'ggpht.com',
        'talkgadget.google.com',
        'picasaweb.google.com',
        'googleusercontent.com',
        'hzmangel.info',
        'slideshare.net',
        'code.google.com',
        'golang.org',
        'vimeo.com',
        'wordpress.com',
        'dxtl.net',
        '123cha.com'
    ];
 
    for(var i=0, l=list.length; i<l; i++) {
        if (isMatchProxy(url, list[i])) {
            alert("Match");
            return Proxy;
        }
    }
 
    alert("direct");
    return 'DIRECT';
}

在PAC中,Firefox和Internet Explore都支持alert语句,IE的表现同普通js一样
Firefox是在  ”浏览器控制台”(Ctrl+Shift+J快捷键调出来) JS标签 里显示出来:


[21:32:29.568] PAC-alert: PAC Debug Information

Machine IP: 192.168.1.99
Hostname: zhiwei.li
Host Resolvable: True
Hostname IP: 199.188.204.95
Plain Hostname: False
Domain Levels: 1
URL: http://zhiwei.li/

正则表达式的另外一个例子

由于.pac 文件支持整个 JavaScript 语言,可以使用正则表达式对象,并测试方法来测试对照正则表达式的字符串。下面的代码示例演示如何使用.pac 文件中的正则表达式对象:

1
2
3
4
5
6
7
8
9
10
11
function FindProxyForURL(url, host)
{
    // For instance, if the server has 4 alphabetic characters,
    // such as "MSDN", route it through a specific proxy:
   var regexpr = /[a-zA-Z]{4}.microsoft.com/;
   if(regexpr.test(host))
      return "PROXY w3proxy:8080; DIRECT";
 
   // Or else connect directly:
   return "DIRECT";
}

http://technet.microsoft.com/en-us/library/dd361950.aspx (微软给的例子)

验证工具

https://code.google.com/p/pacparser/   (支持Python和C)

http://www.jslint.com/ (验证你的js语法)

Debian Jessie中的IceWeasel 24.1.0 对 PAC的支持有问题,
Windows版本的Firefox 26.0就能很好的支持
解决方法,安装 扩炸  foxyproxy
xul-ext-foxyproxy-standard 或者从mozilla addons下载

SOCKS SOCKS4 SOCKS5的问题

“SOCKS host:port”
有的浏览器使用SOCKS4协议,也支持DNS 解析  (IceWeasel 的代理管理,就是这个做法, 但是SOCKS4实际上是不支持 DNS解析的,socks5服务看到协议版本是4, dns请求是未知的,就会直接关掉连接
所以, 你在 firefox里选中socks4协议,就不要 让 extensions.foxyproxy.socks_remote_dns 这个选项为true
但是,如果不做远程dns的话,伟/大的-城_墙 会污染DNS)

有的浏览器使用SOCKS4协议,但不支持 DNS解析
有的浏览器直接使用SOCKS5协议,当然就支持 DNS解析了 (foxyProxy扩展,看到 SOCKS,就直接用SOCKS5了,相当聪明)

“SOCKS5 host:port”   明确说明要用 SOCKS5 代理
据说 Safari (OSX, iOS)只认识SOCKS,虽然它默认也是使用SOCKS5协议

SOCKS5 127.0.0.1:1080; SOCKS 127.0.0.1:1080; DIRECT
这种写法可以兼容绝大数浏览器
对于不认识的SOCKS5,丢掉,认识的SOCKS直接用.

---------------

使用 pac 文件来实现自动代理

pac(proxy autoconfiguration)文件其实就是一个 JavaScript 文件,文件扩展名是什么其实没有关系,但一般都名为 pac

pac 文件中必须包含 FindProxyForURL(url, host) 的函数,支持 pac 自动代理的浏览器将会根据这个函数来判断当前访问的网址走何种通道。最简单的示例如下

function FindProxyForURL(url, host) {
    return 'DIRECT';
}

上面那段代码说明对于所有 url,都直连,不走任何代理。

FindProxyForURL 函数除了可以返回 “DIRECT” 外,还可以返回指定类型、主机和端口的代理。如:

// 本地 3721 端口的 http 代理
"PROXY 127.0.0.1:3721"

// 本地 8080 端口的 socks5 代理
"SOCKS5 127.0.0.1:8080"

可以同时指定多个方式,从第一种开始,一种无法连接使用下一种,直到成功或最后失败,如:

return "PROXY 127.0.0.1:3721; SOCKS5 127.0.0.1:8080; DIRECT";


pac 文件可使用很多已预定义的函数,但在目前为应对封锁的环境中,常用的是功能是让被封锁网址走代理,普通的直连。因此,常用的一个功能函数是:shExpMatch(str, shexp)

shExpMatch 函数是判断字符串 str 是否满足 shexp 表达式。需要注意的是,尽管有着 exp 之名,但 shexp 是仅支持 ? 和 * 通配符的表达式,而非 JavaScript 中的正则表达式,如:

// google 网站走代理,别的直连
function FindProxyForURL(url, host) {
    if (shExpMatch(url, "*.google.com/*")) {
        return 'PROXY 127.0.0.1:3721';
    }

    return 'DIRECT';
}

如果需要做一些较为复杂的判断,那可直接抛弃 shExpMatch 函数,而自己使用正则表达式或别的工具来进行判断,如:

function FindProxyForURL(url, host) {
    // For instance, if the server has 4 alphabetic characters, 
    // such as "MSDN", route it through a specific proxy: 

    var regexpr = /[a-zA-Z]{4}.microsoft.com/;
    if(regexpr.test(host))
        return "PROXY w3proxy:8080; DIRECT";

    // Or else connect directly:
    return "DIRECT";
}

这样,当浏览器支持 pac 自动代理的话,所需要做的工作就是写好 FindProxyForURL 函数,收集好所有的网站数据,然后启用即可,如:

function isMatchProxy(url, pattern) {
    try {
        return new RegExp(pattern.replace('.', '\\.')).test(url);
    } catch (e) {
        return false;
    }

}

function FindProxyForURL(url, host) {
    var Proxy = 'SOCKS5 127.0.0.1:7070; DIRECT;';

    var list = [
        't.co',
        'twitter.com',
        'twimg.com',
        'posterous.com',
        'tinypic.com',
        'twitpic.com',
        'bitly.com',
        'yfrog.com',
        'youtube.com',
        'facebook.com',
        'appspot.com',
        'dropbox.com',
        'flickr.com',
        'youtube.com',
        'ytimg.com',
        'plus.google.com',
        'ggpht.com',
        'talkgadget.google.com',
        'picasaweb.google.com',
        'googleusercontent.com',
        'hzmangel.info',
        'slideshare.net',
        'code.google.com',
        'golang.org',
        'vimeo.com',
        //'appengine.google.com',
        'wordpress.com' 
    ];


    for(var i=0, l=list.length; i<l; i++) {
        if (isMatchProxy(url, list[i])) {
            return Proxy;
        }
    }
    return 'DIRECT';
}
----------------------

Chrome 使用 pac 来自动代理

之所以有此文,是因为忘记在哪个版本起 Chrome 的如 ProxySwitchy 等扩展就有问题了,在代理方面很有问题,没有 Firefox 下的 autoproxy 稳定。在过了一阵子需要翻只能开 FF 的时间后,决定还是看看 Chrome 下该如何解决这个问题。

查看 chromium / google-chrome 的帮助命令,将可以看到和代理(proxy)有关的有:

--proxy-server=host:port
--no-proxy-server
--proxy-auto-detect
--proxy-pac-url=URL

可以看到,Chrome 是支持指定 pac 文件来自动代理的。这样,便可以使用"使用 pac 文件来实现自动代理"一文提到的 pac 文件了。

这样,便可以通过类似下面的命令来启动带自动代理功能的 Chrome 了。

google-chrome --proxy-pac-url=file:///home/user/autoproxy.pac

对于 Windows 环境,直接把 --prox-pac-url=pac-file-path 参数加到快捷方式属性中的『目标』属性的后面即可。

对于 Ubuntu 环境,Chromium 可以通过把这个参数写进 /etc/chromium-browser/default 文件中的 CHROMIUM_FLAGS 变量;对于 google-chrome,暂时没找到方便写配置的地方,干脆直接写个 sh 文件,把整条命令加进去吧(可在命令后加 & 来达到终端关闭浏览器依然存在的目的)

------------------------------------

PAC一般使用一个proxy.pac文件作为配置,若使用http服务器提供pac文件,建议使用的MIME是application/x-ns-proxy-autoconfig

pac文件中其实是javascript代码,其中包含一个重要的函数:

1
function FindProxyForURL(url, host);

浏览器会将请求的URL与主机名传入到这个函数进行查询,函数FindProxyForURL返回一个包含代理服务器信息的字符串,浏览器根据这个字符串使用对应的代理服务器链接网络。

一个简单的pac文件如下:

1
2
3
function FindProxyForURL(url, host) {
return "PROXY proxy.example.com:8080; DIRECT";
}

在这个文件中,所有的网络访问都会使用proxy.example.com:8080代理,若这个代理不可用,则会直接连接(DIRECT)。

 函数列表

在pac文件中可以使用的其他javascript函数如下:

dnsDomainIs 若host匹配google.com例如map.google.com等,则直接连接:

1
2
if (dnsDomainIs(host, ".google.com"))
return "DIRECT";

shExpMatch 若url以.local结尾或在domain.com/folder/目录下则直接连接:

1
2
if (shExpMatch(url, "*.local") || shExpMatch(url, "http://domain.com/folder/*"))
return "DIRECT";

dnsResolve DNS反查IP:

isInNet 若IP在127.16.0.0/12子网内则直接访问:

1
2
if (isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0"))
return "DIRECT";

myIpAddress 返回我当前的IP

1
2
if (isInNet(myIpAddress(), "10.10.1.0", "255.255.255.0"))
return "PROXY 10.10.5.1:8080";

isPlainHostName 若host中不包含“.”则直接访问:

1
2
if (isPlainHostName(host))
return "DIRECT";

localHostOrDomainIs

1
2
if (localHostOrDomainIs(host, "www.google.com"))
return "DIRECT";

isResolvable 若DNS可以被反查则使用代理:

1
2
if (isResolvable(host))
return "PROXY proxy1.example.com:8080";

dnsDomainLevels host中“.”的个数大于0则使用代理:

1
2
3
4
if (dnsDomainLevels(host) > 0)
return "PROXY proxy1.example.com:8080";
else
return "DIRECT";

weekdayRange 周一到周五使用代理:

1
2
3
4
if (weekdayRange("MON", "FRI"))
return "PROXY proxy1.example.com:8080";
else
return "DIRECT";

dateRange 一月到三月使用代理:

1
2
3
4
if (dateRange("JAN", "MAR"))
return "PROXY proxy1.example.com:8080";
else
return "DIRECT";

timeRange 8:00到18:00使用代理:

1
2
3
4
if (timeRange(8, 18))
return "PROXY proxy1.example.com:8080";
else
return "DIRECT";

alert 函数并没有在PAC规范中指定,但IE与FireFox是支持的,用于调试:

1
2
resolved_host = dnsResolve(host);
alert(resolved_host);

 高级应用

一个复杂的pac文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function FindProxyForURL(url, host) {
 
// 一些不使用代理的域名
if (dnsDomainIs(host, ".intranet.domain.com") || shExpMatch(host, "(*.abcdomain.com|abcdomain.com)"))
return "DIRECT";
 
// 对于FTP和abcdomain.com/folder/下的请求不使用代理
 
if (url.substring(0, 4)=="ftp:" || shExpMatch(url, "http://abcdomain.com/folder/*"))
return "DIRECT";
 
// 局域网中的访问不使用代理
if (isPlainHostName(host) ||
shExpMatch(host, "*.local") ||
isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0") ||
isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0"))
return "DIRECT";
 
// 如果我当前的IP地址在10.10.5.0/24子网内则使用代理
if (isInNet(myIpAddress(), "10.10.5.0", "255.255.255.0"))
return "PROXY 1.2.3.4:8080";
 
// 默认的,使用下面的两个代理做负载均衡
return "PROXY 4.5.6.7:8080; PROXY 7.8.9.10:8080";
}

 注意事项

有些浏览器,例如Firefox和Internet Explorer只支持系统缺省编码的PAC文件,不支持Unicode编码的PAC文件,例如UTF-8编码的PAC文件。

函数dnsResolv(及其他类似函数)在执行DNS查询时,如果DNS服务器没有回应,这个会导致你的浏览器被阻塞很长时间.

评论系统从Disqus迁移到Valine

介绍 | Valine

如何方便的使用评论功能就是一件比较麻烦的事情,当然网上也有很多很好的解决方案,例如之前被很多人使用的Disqus,还有多说、网易云跟帖等。但是国内的网络环境下,评论成为了洪水猛兽,于是乎多说、网易云跟帖等国内的评论平台相继关闭,Disqus这样海外的优秀平台也被墙,一时间能够正常使用评论成为了一种奢侈。在这样的大环境下,终于,Valine – 一款极简的评论系统诞生了。今天顺手也把评论从Disqus迁移了过来,正式启用了Valine。

 数据迁移

首先要感谢Deserts Pan大神连夜制作了Disqus的数据迁移工具,经过测试数据迁移也非常简单。

 数据导出

登陆到Disqus后台后,选择Export,即可导出站点下面所有的评论内容。

 数据导入

由于Valine使用LeanCloud来作为评论数据存储的平台,因此首先需要去LeanCloud注册一个账户,注册后在后台创建应用。
创建完成后,需要在应用的设置中,选择“应用KEY”,找到你的APP ID和APP KEY。
然后访问Pan大的Disqus2LeanCloud的后台,输入你刚才的APP ID和APP KEY,并上传你之前在Disqus后台导出的XML文件,点击开始,即可进行数据导入,视你的数据量大小,大约2分钟左右即可完成导入
完成后在LeanCloud后台即可看到导入的Disqus的评论数据了。
另外需要注意的是,这个导入的数据会有一个安全风险,需要手动把ACL的设置里面的权限改为所有人读,否则别人可以轻易删除掉你的站点的评论,这个问题已经提交给Pan大,后续优化掉。

 安全配置

完成数据导入后,需要配置下应用的Web安全域名,限制只有你的站点的域名才能对数据进行访问。

 安装

针对大多数Hexo的博客来说,已经内置了Valine的评论系统,点击这里可以查看到绝大多数Hexo的博客的启用办法,比如对于Hexo的Next的Theme来说,只需要在主题的Config文件里面,修改这一段即可:
1
2
3
4
5
6
7
8
9
10
# Valine.
# You can get your appid and appkey from https://leancloud.cn
# more info please open https://github.com/xCss/Valine
valine:
enable: true
appid: # your leancloud application appid
appkey: # your leancloud application appkey
notify: false # mail notifier , https://github.com/xCss/Valine/wiki
verify: false # Verification code
placeholder: Comment input placeholder
 
把其中的APPID 和APP KEY修改为你对应的LeanCloud上面获取的内容即可。
对于任何第三方页面,也可以通过自己加入代码的方式来使用,样例代码如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Valine - A simple comment system based on Leancloud.</title>
<!--Leancloud 操作库:-->
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<!--Valine 的核心代码库:-->
<script src="./dist/Valine.min.js"></script>
</head>
<body>
<div class="comment"></div>
<script>
new Valine({
// AV 对象来自上面引入av-min.js(老司机们不要开车➳♡゛扎心了老铁)
av: AV,
el: '.comment', //
app_id: 'Your APP ID', // 这里填写上面得到的APP ID
app_key: 'Your APP KEY', // 这里填写上面得到的APP KEY
placeholder: 'ヾノ≧∀≦)o来啊,快活啊!' // [v1.0.7 new]留言框占位提示文字
});
</script>
</body>
</html>
好了,差不多了,如果你看到你的文章页面出现了如下图所示的评论框,那么恭喜你,你已装逼成功,赶紧去炫耀吧。

用微软的Hyper-V编译并安装OpenWRT

由于一些众所周知的原因,国内访问很多海外网站会出现访问速度缓慢甚至打不开的问题,其中不乏一些日常经常使用的例如搜索、邮箱等应用,虽然目前有很多解决方案来解决电脑、手机上面的网络加速问题,但是每个终端都要单独适配非常麻烦,因此直接在路由器端进行配置,让所有连入路由器的设备都可以无感加速,成为了一个相对『完美』的解决方案,因此我在家里的Gen8上面,用Hyper-V虚拟了一个OpenWRT的软路由来提供此类服务。

Hyper-V由于本身不开源,因此OpenWRT的官方编译版本在很早的时候就移除了针对Hyper-V的支持,因此为了让OpenWRT可以完美的运行在Hyper-V上,我们需要自行编译相关驱动组件。当然网上也有很多大神已经编译好的固件,但是大都加入了一些我自己不太使用的功能,作为一个洁癖,当然是自己编译一个了。
    
参考了Chiphell大神tedaz的文章非官方编译,Hyper-V的Openwrt x86和x86-64版,Chaos Calmer正式版后,修改整理如下。

 准备工作

首先你需要准备一个Linux的编译环境,建议选择Ubuntu这类比较流行的Linux发行版本,并参考OpenWRT官方的OpenWRT编译系统-安装,安装好编译所需要的一些依赖包

以Ubuntu 64bit为例,需要执行下面的命令来安装相关的依赖

1
sudo apt-get install build-essential subversion libncurses5-dev zlib1g-dev gawk gcc-multilib flex git-core gettext libssl-dev

 

 修改源码

首先从OpenWRT的官网Git下载OpenWRT的源码,建议下载15.05分支的,Trunk分支下的代码通常不是非常稳定。

1
git clone git://git.openwrt.org/15.05/openwrt.git

 

更新OpenWRT所有的feeds,以便你在后续可以提前把需要的ipk(例如luci、shadowsocks的一些依赖等)打包到固件中

1
2
3
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a

 

下载完成后,需要针对源码进行如下的修改。

修改/package/kernel/linux/modules/virtual.mk,在最后加入下面的内容,修改内核,添加让OpenWRT内核支持Hyper-V

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#
# Hyper-V Drives depends on x86 or x86_64.
#
define KernelPackage/hyperv-balloon
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64)
TITLE:=Microsoft Hyper-V Balloon Driver
KCONFIG:= \
CONFIG_HYPERV_BALLOON \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/hv/hv_balloon.ko
AUTOLOAD:=$(call AutoLoad,06,hv_balloon)
endef

define KernelPackage/hyperv-balloon/description
Microsofot Hyper-V balloon driver.
endef

$(eval $(call KernelPackage,hyperv-balloon))

define KernelPackage/hyperv-net-vsc
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64)
TITLE:=Microsoft Hyper-V Network Driver
KCONFIG:= \
CONFIG_HYPERV_NET \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/net/hyperv/hv_netvsc.ko
AUTOLOAD:=$(call AutoLoad,35,hv_netvsc)
endef

define KernelPackage/hyperv-net-vsc/description
Microsoft Hyper-V Network Driver
endef

$(eval $(call KernelPackage,hyperv-net-vsc))

define KernelPackage/hyperv-util
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64)
TITLE:=Microsoft Hyper-V Utility Driver
KCONFIG:= \
CONFIG_HYPERV_UTILS \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/hv/hv_util.ko
AUTOLOAD:=$(call AutoLoad,10,hv_util)
endef

define KernelPackage/hyperv-util/description
Microsoft Hyper-V Utility Driver
endef

$(eval $(call KernelPackage,hyperv-util))

#
# Hyper-V Storage Drive needs to be in kernel rather than module to load the root fs.
#
define KernelPackage/hyperv-storage
SUBMENU:=$(VIRTUAL_MENU)
DEPENDS:=@(TARGET_x86||TARGET_x86_64) +kmod-scsi-core
TITLE:=Microsoft Hyper-V Storage Driver
KCONFIG:= \
CONFIG_HYPERV_STORAGE=y \
CONFIG_HYPERVISOR_GUEST=y \
CONFIG_PARAVIRT=n \
CONFIG_HYPERV=y
FILES:=$(LINUX_DIR)/drivers/scsi/hv_storvsc.ko
AUTOLOAD:=$(call AutoLoad,40,hv_storvsc)
endef

define KernelPackage/hyperv-storage/description
Microsoft Hyper-V Storage Driver
endef

$(eval $(call KernelPackage,hyperv-storage))</code></pre>

 

修改/target/linux/x86/64/config-default和/target/linux/x86/config-3.18,均添加以下内容(这里后面如果内核有跟心,就修改对应的config-内核版本号即可)

1
2
3
4
5
6
7
8
# CONFIG_HYPERV is not set
# CONFIG_HYPERV_BALLOON is not set
# CONFIG_HYPERV_NET is not set
# CONFIG_HYPERV_STORAGE is not set
# CONFIG_HYPERV_UTILS is not set
# CONFIG_FB_HYPERV is not set
# CONFIG_HID_HYPERV_MOUSE is not set
# CONFIG_HYPERV_KEYBOARD is not set

至此,修改完成。网上还有很多人建议修改Build相关的部分,考虑到后面我们统一使用其他工具来把img转成vhd,因此这一步我们直接生成img即可,不用修改Build相关的内容。

 配置编译参数

OpenWRT有GUI的配置工具,因此我们回到OpenWRT源码主目录,执行make menuconfig,选择Target System为x86,Subtarget有x86_64,以便支持多核心大内存的使用。但是如果你需要在OpenWRT上使用XWare这类只有32位的工具,那就只能编译32位的包了。

f:id:briteming:20180718164729p:plain

f:id:briteming:20180718164906p:plain

然后在Kernel modules里的Virtualization Support里勾选上4个Hyper-V相关的。

https://archive.is/wdj36/71dd3fa1e531c5f921b4590a12c0e8416165ccc0

 

最后取消Kernel modules里的Network Devices中其他网卡即可。
当然,如果你希望提前编译类似于shadowsocks之类的工具,可以参考Shadowsocks OpenWRT上的说明,下载相应的package并在配置编译参数时选中这个包即可,相关依赖会自动选中。

 开始编译

使用命令make可以进行编译,make V=s可以让它输出调试信息,带上-j1参数表示用1个核心编译。建议你选择一台4核心以上的机器来进行编译以免等待的时间太久,由于编译过程中需要下载很多内容,因此流畅的网络(能自动翻墙是最好的)会大大加快你的编译速度。

我之前使用了E3-1230V2的CPU,用了6个核心编译,首次编译大概花了接近1小时的事件才全部编译完成。

 转换格式,大功告成

编译完成后,在BIN目录下,可以找到编译完成的img文件(一般是压缩包),解压后,我们使用下面的命令来转化为Hyper-V可用的vhd格式。

1
qemu-img convert -f raw -O vpc openwrt-x86-generic-combined-ext4.img openwrt-x86-generic-combined-ext4.vhd

 

然后直接在Hyper-V下面使用就一切OK啦。

from 

http://archive.is/wdj36

使用DNS-Forwarder提升ChinaDNS稳定性

很多人使用Openwrt的路由器配合SS来提升访问海外网站的速度和稳定性,其中ChinaDNS被很多人作为防DNS污染的利器,但是大多数人目前还是使用ss-tunnel创建一个UDP转发隧道作为ChinaDNS的上游来进行查询,这在不少地区的ISP环境下常常出现不稳定的现象,aa65535的DNS-Forwarder for OpenWrt很好的解决了这个问题,参考Wiki整理如下:

 安装DNS-Forwarder for OpenWrt

从v1.1.0版本开始,DNS-Forwarder for OpenWrt把Luci设置界面分离到了OpenWRT-Dist-Luci,因此根据你的平台不同,你需要分别下载两个程序:

下载完成后,在路由器上执行opkg install安装即可

 配置DNS-Forwarder和ChinaDNS

DNS-Forwarder配置比较简单,只需要设置监听端口和上游DNS即可,这里我设置了监听端口为5352

然后配置ChinaDNS的上游服务器,把原先使用UDP隧道转发的上游去掉,改为DNS-Forwarder的地址,这里是127.0.0.1:5352,另一个上游服务器保持不变,可以是114.114.114.114这种公共DNS,也可以是你的ISP的DNS

 完成

设置完成,如果你第一次使用ChinaDNS的话,需要在网络-DHCP/DNS中,把ChinaDNS配置为本地的DNS服务器,如下图所示,如果之前已经配置了,那这一步就可以忽略了。

在这个模式下,ChinaDNS使用DNS-Forwarder作为上游,而DNS-Forwarder又使用TCP协议直接向上游(通常是8.8.8.8)服务器进行查询,如果配合了SS,TCP查询会自动走SS线路,也同时解决了线路优化的问题.

Linux服务器的IP配置攻略

在Linux 网络设备在配置时被赋予别名,该别名由一个描述性的缩略词和一个编号组成。某种类型的第一个设备的编号为 0,其他设备依次被编号为 1、2、3,等。但是网卡并不是作为裸设备出现在/dev目录下,而是存在内存中。eth0, eth1是以太网卡接口。它们用于大多数的以太网卡,包括许多并行端口以太网卡。本文主要讨论这类网卡。 为Linux以太网卡设定IP地址的方式非常灵活,你可以选择适合你工作情况的方法:
1. 使用ifconfig命令

ifconfig命令是最重要的Linux网络命令之一,最主要的用途是设定、修改网卡的IP地址,修改网卡ip地址:
# ifconfig eth0  192.168.149.129 netmask 255.255.255.0
默认情况下, ifconfig 显示活动的网络设备。给这个命令添加一个 -a 开关就能看到所有设备。但是ifconfig命令设置网络设备的ip地址系统重新启动后设置会自动失效。所以它主要用于网卡状态调试。假设您要建立一个临 时的网络配置以供测试。您可以使用发行版本中的工具来编辑配置,但是需要注意在完成测试之后,将所有设置恢复回去。通过使用 ifconfig ,我们无需影响已保存的设置,就能够快速地配置网卡。
查看指定网卡的接口状态:
#ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:0C:29:F6:9B:27
inet addr:192.168.149.129  Bcast:192.168.149.255  Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fef6:9b27/64 Scope:Link
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:120 errors:0 dropped:0 overruns:0 frame:0
TX packets:116 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:12600 (12.3 KiB)  TX bytes:12705 (12.4 KiB)
Interrupt:10 Base address:0x1424
可以看到修改后 的ip地址生效。小贴式:ifconfig修改的ip地址,在服务器重新启动后会失效。
2. 使用ip命令
ip命令是iproute2软件包里面的一个强大的网络配置工具,它能够替代一些传统的网络管理工具。例如:ifconfig、route等。 现在,绝大多数 Linux 发行版和绝大多数 UNIX都使用古老的arp, ifconfig和route命令。虽然这些工具能够工作,但它们在Linux2.2和更高版本的内核上显得有一些落伍。使用iproute2前你应该确 认已经安装了这个工具。这个包的名字在RedHat Linux 9.0叫作“iproute2”,也可以在:ftp://ftp.inr.ac.ru/ip-routing/ 下载源代码安装。如果希望在以太网接口eth0上增加一个地址10.0.0.1,掩码长度为24位,标准广播地址,标签为eth0:Alias:
#ip addr add 10.0.0.1/24 brd + dev eth0 label eth0:Alias
3. 使用 netconfig命令
netconfig命令可以设置网络设备的ip地址,netconfig命令可以永久保存设置。
使用方法是:“netconfig ethX”。使用命令“netconfig eth0”后会在命令行下弹出一个对话框进行确认,选择“是”,如图1 。
图1 是否进行联网配置对话框
这时即可进行设定见图2
图2 netconfig配置界面
设定结束后用“tab”键选择“OK”即可保存设置并且退出。然后使用命令激活即可生效:
#service network restart
或者使用等价命令组(先禁用后启用):
#ifdown eht0
#ifup eth0
小贴士:netconfig命令修改的ip地址,在服务器重新启动后不会失效。
4. 使用neat命令

使用neat命令需要配置好X window系统,在命令行下运行“neat”命令后添加IP地址和其他相关参数后保存设置,从新启动网络和网络服务或计算机,见图3。
图3 图形界面添加IP地址
另外neat命令还有一个同价命令:“redhat-config-network”,二者完全相同。Neat和redhat-config-config命令可以永久保存设置。
5. 修改TCP/IP网络配置文件
除非另行指定,Red Hat Linux 系统中大多数配置文件都在 /etc 目录中。网卡相关的TCP/IP网络配置文件是:/etc/sysconfig/network-scripts/ifcfg-ethx。其中x从0开 始,第一个以太网配置文件即:/etc/sysconfig/network-scripts/ifcfg-eth0。使用vi编辑器修改这个文件,也可 以修改网卡IP地址。比如文件:ifcfg-eth0  代表是以太网实际网卡0的配置文件,比如文件:ifcfg-eth0:1  代表是以太网实际网卡0的配置文件。
#vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0        #设定网卡的名称,要跟文件名称对应 #
ONBOOT=yes        #是否在开机的的时候启动网卡#
BOOTPROTO=static      #启动的时候的 IP 取得的协议,这里是固定的,
如果是动态主机的话,要改成 dhcp 才行#
IPADDR=192.168.1.2     #IP 地址#
NETMASK=255.255.255.0   #子网掩吗#
NETWORK=192.168.1.0    #该网段的第一个 IP#
BROADCAST=192.168.1.255  #最后一个同网段的广播地址#
GATEWAY=192.168.1.2    #网关地址#
#GATEWAYDEV=eth0
存盘后使用命令:“service network restart “激活即可生效。这个方法同样可以永久保存设置。
6. 在一个网卡上配置多个ip地址
有时候想要在网卡上配置多个ip地址,同样可以使用ifconfig命令完成:
ifconfig eth0:1 192.168.149.122 netmask 255.255.255.0
ifconfig eth0:2 192.168.149.123 netmask 255.255.255.0
以上是对网卡eth0修改了2个IP地址的方法,重新使用ipconfig命令查看,可以看到一个网卡上已经配置多个ip地址。如图4。
图4在一个网卡上配置多个ip地址
7. 无线网卡在Linux下的ip配置全攻略
随着Linux网络技术的快速增长,硬件厂商大大加速对硬件产品对Linux的技术支持。使得Linux 支持的无线网卡的数量在过去的一两年里增长显著。对于有些设备,配置无线连接非常简单:只要在您使用的 Linux 发行版本,插入无线网卡,在设置过程中单击鼠标,并输入正确的联网参数就可以了。设置无线网络相关步骤如下:
(1)用“iwconfig”命令来显示无线网卡(eth0、eth1)的信息。在以下的步骤中,用ethX表示无线网卡的名称。
(2)设置无线网卡的操作模式为Managed:
#iwconfig ethX mode Managed
(3)如果采用了WEP加密,需要设置WEP密码:
#iwconfig ethX key password XXXXXX
对应40位和128位加密,password分别为6位和10位的十六进制数字。
(4)设置SSID,其中ESSID为无线接入(Access Point)的SSID。
# iwconfig ethX essid ESSID
(5)启动无线网卡:
#ifconfig ethX up
总结:
可以看到Linux 下网卡的ip设置的方法比较灵活,不同的命令可以完成相同的任务。注意由于ip地址是Linux服务器的关键参数所以完成以上操作要有管理员权限。
from archive.is/13svf
--------------------------
 
Linux服务器如何一个网卡绑定多个IP
 

系统:Redhat9
目的:为一个以太网卡配置多个ip地址

    linux操作系统中配置网络接口,一般是通过网络配置工具实现,但实质是修改与网络相关的配置文件起作用,故可直接修改文件达到目的。
   由于发行版本不同,其有自己专用的配置工具,但也有一些通用的配置工具,如ifconfig,ifup,ifdown
查看
#ifconfig      //当前网络接口情况
#ifconfig -a   //主机所有网络接口情况
#ifconfig eth0 //eth0接口情况

配置
1.ifconfig
格式:ifconfig 网络设备 ip地址 hw MAC地址 netwask broadcase地址 … …
(详见ifconfig –help)
例如:#ifconfig eth0 192.168.1.41 broadcase 192.168.1.255 netmask 255.255.255.0
注:用ifconfig为网卡指定ip只是用来调试网络用,并不会更改系统网卡相关的配置文件。

2.rh9网络配置工具netconfig
格式:netconfig -d 网络设备 –ip –hwaddr –netmask ……
(详见netconfig –help)
例如:#netconfig -d eht0 –ip=192.168.1.41 –netmask=255.255.255.0
注:直接修改网络接口相关的配置文件

3.修改网络配置文件
rh中与以太网相关的配置文件位于:/etc/sysconfig/network-scripts目录下,如ifcfg-eth0。可以增加配置文件如ifcfg-eth1来增加新的网络接口。
激活和终止
格式:ifconfig 网络设备 up/down
     或ifup/ifdown 网络设备
例如:#ifconfig eth0 up
虚拟网络接口
即:为一个网卡配置多个ip
与一般配置基本相同,只是一般网络接口是eth0,eth1,…,而虚拟网络接口为:(以eth0为例)eth0:0,eth0:1,eth0:2,…
另外需要注意的是在设置虚拟接口时,每个接口都有不同的物理地址
例如:#netconfig -d eth0:0 –ip=192.168.1.42 –hwaddr=00:11:00:00:B1:05 –netmask=255.255.255.0 –broadcase=192.168.1.255
(eth0:hw是00:11:00:00:B1:04)