elasticsearch 创建 mapping

  • 查看当前ES中有哪些索引

    1
    2
    3
    4
    5
    6
    7
    8
    [GET] http://localhost:9200/_cat/indices

    返回:
    {
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "inde_name"
    }
  • 创建索引(index)(mysql-库)

    1
    2
    3
    4
    5
    6
    7
    8
    [PUT] http://localhost:9200/inde_name

    返回:
    {
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "inde_name"
    }
  • 查看索引

    1
    2
    3
    4
    5
    6
    7
    8
    [GET] http://localhost:9200/inde_name/_mapping

    返回:
    {
    "inde_name": {
    "mappings": {}
    }
    }
  • 创建类型(type)(mysql-表)的同时创建创建映射(mapping)(mysql-字段)

    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
    [POST] http://localhost:9200/inde_name/_mapping/fans

    body:
    {
    "dynamic": "false",
    "_all": {
    "enabled": false
    },
    "_parent": {
    "type": "kol"
    },
    "_routing": {
    "required": true
    },
    "properties": {
    "fansAge": {
    "type": "integer"
    },
    "fansCity": {
    "type": "keyword"
    },
    "fansCityLevel": {
    "type": "integer"
    },
    "fansGender": {
    "type": "integer"
    },
    "fansInterests": {
    "type": "keyword"
    },
    "fansKolUid": {
    "type": "keyword"
    },
    "fansLocation": {
    "type": "keyword"
    },
    "fansProvince": {
    "type": "keyword"
    },
    "fansUid": {
    "type": "keyword"
    }
    }
    }

    返回:
    {
    "acknowledged": true,
    }
  • 再次查看索引

    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
    [GET] http://localhost:9200/inde_name/_mapping

    返回:
    {
    "inde_name": {
    "mappings": {
    "fans": {
    "dynamic": "false",
    "_all": {
    "enabled": false
    },
    "_parent": {
    "type": "kol"
    },
    "_routing": {
    "required": true
    },
    "properties": {
    "fansAge": {
    "type": "integer"
    },
    "fansCity": {
    "type": "keyword"
    },
    "fansCityLevel": {
    "type": "integer"
    },
    "fansGender": {
    "type": "integer"
    },
    "fansInterests": {
    "type": "keyword"
    },
    "fansKolUid": {
    "type": "keyword"
    },
    "fansLocation": {
    "type": "keyword"
    },
    "fansProvince": {
    "type": "keyword"
    },
    "fansUid": {
    "type": "keyword"
    }
    }
    }
    }
    }
    }

elasticsearch 常用命令

以下查询样例均在 ES 5.6.1 版本进行

  • 下载样例数据

    1
    https://github.com/Witee/statics/blob/master/blog/elasticsearch/example-data/accounts.json
  • 写入 ES

    自动创建了索引 bank,类型 account,使用bulk接口批量操作

    1
    curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary  @accounts.json
  • 查看索引

    1
    curl 'localhost:9200/_cat/indices?v'
  • 普通查询

    • 匹配所有;
    • account_number 升序;
    • 从第 3 条记录开始(注意这里的 from 不表示页码);
    • 每页显示 2 条;
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
    "query": {
    "match_all": {}
    },
    "sort": {
    "account_number": {"order": "asc"}
    },
    "from": 3,
    "size": 2
    }

    sort 可以写多条

    1
    2
    3
    4
    "sort": [
    {"balance": {"order": "desc"} },
    {"account_number": {"order": "asc"} }
    ]

    _source 中指定返回字段

    1
    "_source": ["account_number", "balance"]

match 会对查询关键词先进行分词,再查询

address 包含 milllane,不区分大小写

1
2
3
{
"query": { "match": { "address": "mill lane" } }
}

address 包含 milllane,不区分大小写

1
2
3
{
"query": { "match_phrase": { "address": "mill lane" } }
}

解决 webpack4 设置全局模块找不到的问题

webpack4.x设置全局模块使用的是 ProvidePlugin,其中 open-js-tools 是自定义的模块,已经上传至 npm,但在使用时提示未找到。

1
2
3
4
5
new webpack.ProvidePlugin({
moment: 'moment',
_: 'lodash',
JsTools: 'open-js-tools',
})

原因是在导出时的设置问题,即不能添加 default

1
2
3
4
5
import string from './libs/string';

export.default {
string,
};

应该使用:

1
2
3
4
5
import string from './libs/string';

export {
string,
};

使用 default后,路径应该是JsTools.default.string

如何扩展 antd 的 icon

antd 自带的 icon 相信大家都会用了,<Icon type="team" /> 就搞定了,简直不能更方便了。

但是PM提需求了,team的图标要3个人的,现在是2个人。。。

所以这里教大家如何进行扩展。

  • 打开 http://iconfont.cn/ 搜索 team,找到想要的图标,大家可以参考官方的使用方法生成想要的图标.

  • 在选择代码的时候要选Unicode方式,因为 antd 用的就是这种方式,就像使用字体一样使用图标。

  • 点击下面的复制代码,如下

    1
    2
    3
    4
    5
    6
    7
    8
    @font-face {
    font-family: 'iconfont'; /* project id 403570 */
    src: url('//at.alicdn.com/t/font_403570_giurk9b0g3hxgvi.eot');
    src: url('//at.alicdn.com/t/font_403570_giurk9b0g3hxgvi.eot?#iefix') format('embedded-opentype'),
    url('//at.alicdn.com/t/font_403570_giurk9b0g3hxgvi.woff') format('woff'),
    url('//at.alicdn.com/t/font_403570_giurk9b0g3hxgvi.ttf') format('truetype'),
    url('//at.alicdn.com/t/font_403570_giurk9b0g3hxgvi.svg#iconfont') format('svg');
    }
  • 再添加字义字体的样式代码,同样在帮助中有,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    .iconfont {
    font-family: "iconfont" !important;
    font-size: 14px;
    font-style: normal;
    -webkit-font-smoothing: antialiased;
    -webkit-text-stroke-width: 0.2px;
    -moz-osx-font-smoothing: grayscale;
    }
  • 将以上代码放到你的 css 文件中,并引入项目。

    之后就可以使用图标了:

    1
    <i class="iconfont">&#xe624;</i>

    其中 &#xe624; 就是你的图标名称。

  • 注意 antd 的图标都有一个 anticon 的类,所以一般情况下你需要这样使用图标:

    1
    <i class="iconfont anticon">&#xe624;</i>
  • 至此正常使用图标已经没有问题了

    但是,我还有个特殊的情况,我的图标是在侧边导航,在点击折叠导航时图标的大小会变化,也就是font-size:14px16px,折叠的时候图标会变大,所以我的 css 样式还需要增加一行:

    1
    2
    3
    .ant-menu-inline-collapsed .iconfont {
    font-size: 16px !important;
    }

    其中 ant-menu-inline-collapsed是折叠之后增加的类,所以这样设置就没有问题了。

  • 搞定
    希望可以帮助到大家。

Python 字符编码问题

参考文档 http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819196283586a37629844456ca7e5a7faa9b94ee8000

ASCII、Unicode和UTF-8在现在计算机系统通用的字符编码工作方式:
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

  • 推荐的使用方式
    在 python 文件顶部习惯上会指定编码 #coding:utf8 ,所以在文档中出现的内容全部使用
    UTF-8 处理

  • unicode 与 UTF-8 转换方法

    • u’xxx’转换为UTF-8编码的’xxx’用encode(‘utf-8’)方法

      1
      2
      3
      4
      >>> u'ABC'.encode('utf-8')
      'ABC'
      >>> u'中文'.encode('utf-8')
      '\xe4\xb8\xad\xe6\x96\x87'
    • 把UTF-8编码表示的字符串’xxx’转换为Unicode字符串u’xxx’用decode(‘utf-8’)方法

      1
      2
      3
      4
      5
      6
      >>> 'abc'.decode('utf-8')
      u'abc'
      >>> '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
      u'\u4e2d\u6587'
      >>> print '\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
      中文
  • json 在使用中的字符问题

json 在 dumps 之后,再 Loads 回来,会变成 unicode,所以按照上面的习惯,
在使用的时候应该进行 unicode -> utf-8 的转换 u'ABC'.encode('utf-8')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@serv ~]# python
Python 2.7.3 (default, Jun 1 2015, 14:36:54)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> d = {'a': '中文asdf123'}
>>> print type(d['a'])
<type 'str'>
>>> dd = json.dumps(d)
>>> print dd
{"a": "\u4e2d\u6587asdf123"}
>>> d1 = json.loads(dd)
>>> print d1
{u'a': u'\u4e2d\u6587asdf123'}
>>> print type(d1)
<type 'dict'>
>>> print d1['a']
中文asdf123
>>> print type(d1['a'])
<type 'unicode'>

git 在 fork 一个别人的库之后,源更新的同步

gitlab或github下,a开发者fork了b开发者的项目后,如果b开发人员更新代码后,a开发者如何获得更新?

  • 给fork配置远程库

使用 git remote -v 查看远程状态
确定一个将被同步给 fork 远程的上游仓库

git remote add upstream https://github.com/你fork的库地址

git remote -v 再次查看状态确认是否配置成功。
如果成功会出现两个以upstream开头的

  • 同步fork
    从上游仓库 fetch 分支和提交点,提交给本地 master,并会被存储在一个本地分支 upstream/master

先切换到本地主分支

git checkout master

把 upstream/master 分支合并到本地 master 上,这样就完成了同步,并且不会丢掉本地修改的内容。

git fetch upstream

  • 将源仓库的内容合并过来(更新)
    git merge upstream/master

如果想更新到 GitHub 的 fork 上,直接

git push origin master

就好了。

二进程方式安装 NodeJs

  • 下载地址:

    1
    https://nodejs.org/download/release/v5.12.0/

    上级目录有其它版本,找到64位的二进制版本:

    1
    node-v5.12.0-linux-x64.tar.gz
    • 下载、解压,然后放到 /usr/local 目录中
    1
    2
    3
    4
    5
    6
    [root@serv node-v5.12.0-linux-x64]# pwd
    /usr/local/node-v5.12.0-linux-x64
    [root@serv node-v5.12.0-linux-x64]# ls
    bin CHANGELOG.md include lib LICENSE README.md share
    [root@serv node-v5.12.0-linux-x64]# ./bin/node -v
    v5.12.0

    node -v 可以出现版本号,证明可以使用

  • nodenpm 命令添加至系统搜索路径

    1
    2
    [root@serv node-v5.12.0-linux-x64]# ln -s /usr/local/node-v5.12.0-linux-x64/bin/node /usr/bin/node
    [root@serv node-v5.12.0-linux-x64]# ln -s /usr/local/node-v5.12.0-linux-x64/bin/npm /usr/bin/npm
  • 安装完成

转:如何学习一门程序语言

url: http://mp.weixin.qq.com/s/I3poFjvVi31rWyzLhtDcVA

避免看到最后说我诓你,这篇其实应该是《我是如何学习一门程序语言的》。

对我而言,不同的语言,学习的方法似乎也不太一样。

最早的时候都是在学校里学的,比如 Fortran、C、C++、Java、OCaml 等。通过正式的课程去学习一门语言,方式会比较固定和统一,都是上课、做作业、以及编程作业。这种方式通常可以比较系统地了解语言各方面的特性,而实际实践还是要看各人的机遇和选择。所以有一些语言,上完课之后,却是很少再用了。

离开学校后,很多工作中再接触到的语言就属于自学了。总的说来有三点感触。

一是不要为了学习一门语言而学习。至少你知道自己在不远的将来有很大可能性会用再去学。因为学了一门语言而不去实践,除了对语言特性能有些了解,其实不会有什么用。因为很多东西肯定会忘掉。这有的时候和一门说话的语言一样。大学的时候觉得好玩学了日语和德语,然而从来没有真正的应用场景,所以都忘的差不多了。都不好意思跟别人说我学过。不过以后需要用的时候可能学起来还是比从头开始快些吧。

二是不同语言别人口中的学习的难度和你自己学起来觉得的难度会很不一样。原因就在于你已经熟悉掌握的语言其实是你的底子。比如一个已经熟悉 OO 编程的人,再学另一门 OO 语言就会相对轻松;一个已经熟悉函数式编程的人,再学习另一门函数式语言也会比从没接触过的人容易的多。

但这仅限于相对轻松。每门语言都还是有很多区别于同类语言的特性。还有很多语言,是综合了多个类型语言的特性,再做了不同的权衡。即使是看似语法很相近的语言,可能实际使用起来却又有很大的区别。一个众而周知的例子就是 C++ 和 Java。二者都是典型的 OO 语言,然而使用起来很多思维方式却是有着极大的差异。因此,学习一门语言很忌讳肤浅的觉得 “这个和我知道的 X 语言差不多”,然后想当然的在使用中套用一些 X 语言的思维。

三是因为工作时候学习语言通常都是边用边学。一方面,这比在学校时候能够学的更快,因为你有使用的场景,可以不断练习。而且周围很多高手可以讨论,还有别人的代码可以参考,更容易积累实战经验。而另一方面,直接上手没有系统学习很容易想当然,很容易以偏概全。这又必须在工作以外自己主动学习理论知识来弥补。

说几个我工作中学习语言的例子。

首先说 Scala。需要用 Scala 的时候,是一个别组的项目有特别紧的 Deadline,我因为一向比较 “手快” 且对业务逻辑比较熟,所以被借调过去帮忙。那时候我并没有学过 Scala,但是因为时间关系,必须立马上手。好在面向对象语言和函数式设计语言我都有比较好的底子。所以在已有代码库的基础上写一些新的函数,而不需要我去写架构代码,总的来说还是比较轻松的。

但是用 Scala 写 Spark 相关的代码,逻辑正确是不够的,一定要对代码执行的性能有所考虑。比如需要知道一些常见函数大概的时间代价,例如 group by 和 order by 其实都是比较昂贵的,应该避免一些不必要的频繁使用。而有些操作又是相当低代价,可以随意使用。另一个就是 Lambda 嵌套使用过程中语言的一些局限性等。好在组里当时有几个 Scala 比较熟的,所以一些不规范或者低效的使用方式,在 Code Review 中也会被指出。所以,几个月后,虽然用 Scala 也写了不少代码,过程中也了解了很多这样的易出错的地方,但是感觉如果不是因为是在一个协作的过程中有人帮忙,这种裸上写代码的方式还是可能引起一些性能上自己没有意识到的问题。

再说说 Ruby 以及 Rails。Ruby 是语言,Rails 是框架,但是实际工作中极大多数时候 Ruby 都是在 Rails 下使用的。因此放到一起说。Ruby 语言语法简单、使用灵活,看似好学,其实又是最难学的语言之一。因为总和其配对的 Rails 中的 Magic 太多。很多在别的语言上挺有造诣的朋友,对这门语言/框架自学和速成都遇到一些困难。Ruby / Rails 其实是我最精通的语言/框架之一,却也是我学习的时间最长的语言/框架之一。一来在 Square 的时候 Rails 就是主要(语言)架构,且公司有很多 Rails 的专家大牛,所以给了我一个极好的学习氛围。且 Airbnb 也是重度使用 Rails。二来因为常用,所以自己也愿意额外下功夫,整个 RailsCast 几百段教学录像,当时借用每天上下班坐车的时间都看完了。一些 Rails 的论坛也常常关注。所以对于 Rails,虽然坑很多,但是自己还是有信心能避开大部分常见的问题。之前的一篇《聊聊 Ruby on Rails》也写过一些心得体会。

最后说说几种前端语言、框架、和库的学习,例如 JavaScript,Ember,React 等。我在学校的时候其实从来没有碰过前端。后来因为工作需要才去学的这几种。前端语言和后端语言差异还是蛮大的,尤其是语法上。如果一点底子都没有,加上 Html,CSS 等,其实有时候读懂代码都费劲。所以直接上手写几乎是没有可能了。

当时一开始是找的 W3School 上的一些教程类文档,完整地过了一篇,不算很长,看起来倒也挺快。看完读代码问题就不算太大。然后白天看看公司的代码库,写一些简单的代码练手。一有空,就拿语言的官方文档边看边抄。什么意思呢?就是从头细读,遇到能立马理解体会的,根据熟悉程度,或快或慢,一带而过。遇到有点不知其所以然,或者虽然理解了,但是觉得自己没有深刻体会的的,就做笔记摘录下来。这样有一些在实践的过程中慢慢又会遇到,通过实际场景就会更深刻地理解。不时再温习一遍自己的笔记,觉得已经熟悉掌握的就划掉。学和练交替,等到笔记上半懂不懂的内容全部被 Mark 了,基本也算学的差不离了。

大致就是如此吧。

最后说一下,语言毕竟只是工具。精通一门语言最多算是优势,从长久的职业生涯来说,只能算技能之一。简历上多列几门语言也不见得就在找工作的时候一定有优势。有一定的语言功底,每种典型的语言类型都能熟悉或精通一门。然后在需要的时候再去学,学习的过程中能做到不想当然,不套用定式。

其实没有绝对好或者绝对不好的语言,因为每种语言都是为了一些特定场景设计的。脱离了这些场景,就总有用起来比较尴尬的情况。多了解语言的特性,在使用过程中能做到扬长避短,大部分时候就足够了。当然,如果是项目里负责语言架构的技术人员,那又另说了。

为开源做贡献,github 发布项目时的结构化仓库模板

  • 前言

工作中经常会写一些小工具,不管是内部还是外部,都想用通用的方式发布出去,这样别人就能使用,不用再“重复造轮子”。
这里以 python 为例,介绍项目中的一些使用习惯,方便其他人理解、使用

  • 仓库模板

https://github.com/Witee/project-template

  • 目录介绍

    1. docs/ : 放置参考文档
    2. myPkgName/ : 真正的包目录
    3. tests/ : 测试本项目的测试脚本目录
  • 文件介绍

    1. README.md : 使用 markdown 语法介绍本项目的情况
    2. setup.py : 本项目如何安装到系统中
    3. .gitignore : git 中忽略的文件
    4. 可选的文件:
      • requirements.txt
      • Makefile
      • LICENSE
  • 说明
    通过以上的目录及文件,用户就可以明白它们的作用,快速的使用你的项目。

  • 注意
    setup.py 中是将项目路径写入 .pth 文件中实现 python 可以搜索到的。

原创:使用 shadowsocks + dnsmasq + ipset + iptables 实现公办网络透明代理(智能翻墙)

update:
根据 《中华人民共和国网络安全法》的相关规定,“翻墙”是违法行为,本文仅作为学习、交流使用。

网上大多数写的都是关于 openWRT 路由器关于 shadowsocks 的配置,
我这里写的是关于办公网络的配置,希望对大家有所帮助。

  • 网络拓扑

    images

  • 网关服务器有两块网卡,eth1为内网,eth0为外网,通过iptables nat转发将内网包转发到外网,

    1
    -A POSTROUTING ! -s 192.168.2.1/32 -j SNAT --to-source xxx.xxx.xxx.xxx

    以下是 iptables 相关表与链的图,帮助理解 iptables 的设置:

    iptables

  • 网关安装 dnsmasq 提供本地dns服务
  • 通过代理服务器访问国外网站的结构图

    tuopu2

  • 代理服务器上安装:

    • 安装依赖包

      1
      yum install build-essential autoconf libtool openssl-devel gcc git -y
    • 安装 shadowsocks

      1
      2
      3
      git clone https://github.com/shadowsocks/shadowsocks-libev.git  
      cd shadowsocks ; ./configure —prefix=/usr/local/shadowsocks
      make; make install; mkdir /usr/local/shadowsocks/etc/
    • shadowsocks 配置文件,ss-localss-serverss-redir 都是同样的配置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      cat /usr/local/shadowsocks/etc/config.json
      {
      "server":”your.server.ip.x",
      "server_port”:1194,
      "local_port":1080,
      "password”:”your_passwd",
      "timeout":600,
      "method":"aes-256-cfb"
      }
      解释:
      "server":"[服务器IP地址]",
      "server_port":[服务器端口],
      "local_port":[本地端口],
      "password":"[密码]",
      "timeout":600,
      "method":"[加密方式]"
      }
    • 启动脚本

      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
      [root@localhost ~]# cat /etc/init.d/shadowsocks

      start() {
      echo "Starting ss-server..."
      /usr/bin/nohup /usr/local/shadowsocks/bin/ss-server -c /usr/local/shadowsocks/etc/config.json >>/tmp/shadowsock.log 2>&1 &

      }
      stop() {
      echo "Stopping ss-server..."
      killall ss-server
      }

      case $1 in
      start)
      start
      ;;
      stop)
      stop
      ;;
      *)
      echo "Usage : $0 start|stop"
      ;;
      esac

      chmod 755 /etc/init.d/shadowsocks
      /etc/init.d/shadowsocks start
  • 网关服务器上安装:

    • shadowsocks安装方法同上,配置文件一致,启动脚本有所修改:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      [root@localhost ~]# cat /etc/init.d/shadowsocks
      #!/bin/bash

      start() {
      echo "Starting ss-redir..."
      /usr/bin/nohup /usr/local/shadowsocks/bin/ss-redir -c /usr/local/shadowsocks/etc/config.json >>/tmp/shadowsock.log 2>&1 &

      }
      stop() {
      echo "Stopping ss-redir..."
      killall ss-redir
      }

      case $1 in
      start)
      start
      ;;
      stop)
      stop
      ;;
      *)
      echo "Usage : $0 start|stop"
      ;;
      esac
    • 网关服务器上使用的是 ss-redir,也就是透明代理会使用到的程序,如果只是本地用来上网的话,使用 ss-local
      到此代理服务器与网关服务器的隧道就建立好了。

  • 将经过网关服务器的请求转发至本地的隧道,也就是 1080 端口,达到代理的目的,但是这样的话,所有的请求都会使用代理,所以要反过来做,将指定IP的请求转发至隧道。

    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
    [root@localhost tmp]# cat ss-black.sh
    #!/bin/sh

    #create a new chain named SHADOWSOCKS
    iptables -t nat -N SHADOWSOCKS

    #Redirect what you want

    #Google
    iptables -t nat -A SHADOWSOCKS -p tcp -d 74.125.0.0/16 -j REDIRECT --to-ports 1080
    iptables -t nat -A SHADOWSOCKS -p tcp -d 173.194.0.0/16 -j REDIRECT --to-ports 1080

    #Youtube
    iptables -t nat -A SHADOWSOCKS -p tcp -d 208.117.224.0/19 -j REDIRECT --to-ports 1080
    iptables -t nat -A SHADOWSOCKS -p tcp -d 209.85.128.0/17 -j REDIRECT --to-ports 1080

    #Twitter
    iptables -t nat -A SHADOWSOCKS -p tcp -d 199.59.148.0/22 -j REDIRECT --to-ports 1080
    iptables -t nat -A SHADOWSOCKS -p tcp -d 205.164.0.0/16 -j REDIRECT --to-ports 1080

    #Shadowsocks.org
    iptables -t nat -A SHADOWSOCKS -p tcp -d 199.27.76.133/32 -j REDIRECT --to-ports 1080

    #1024
    iptables -t nat -A SHADOWSOCKS -p tcp -d 184.154.128.246/32 -j REDIRECT --to-ports 1080

    #Anything else should be ignore
    iptables -t nat -A SHADOWSOCKS -p tcp -j RETURN

    # Apply the rules
    iptables -t nat -A PREROUTING -p tcp -j SHADOWSOCKS

    以上是网上的脚本,只有列表中的地址会使用代理。
    但是这样就得手工维护这个地址,所以要使用更智能的方法,也就是自动获得这些IP地址。

    方法是:通过无污染的DNS请求域名,把解析后的IP写到列表中。

  • 具体实施:

    • yum install ipset: ipset 的使用方法及 ipsetiptables 的关系请自行 google

    • ipset -N setmefree iphash:新建一个 IP 的池子,通过 ipset list 命令可以查到池中的 IP,现在是空的

    • 添加 iptables

      1
      2
      3
      iptables -t nat -A PREROUTING -p tcp -m multiport --dports 443 -m set --match-set setmefree dst -j REDIRECT --to-ports 1080
      iptables -t nat -A PREROUTING -p tcp -m multiport --dports 80 -m set --match-set setmefree dst -j REDIRECT --to-ports 1080
      iptables -t nat -A PREROUTING -p tcp -j RETURN

      tcp 请求的 80 443 端口并且是在池中的目的地址转发至 1080 端口(使用代理);其它不使用代理。
      其中 setmefree 名称要与 ipset -N 时使用的名称一致。

    • 现在池中的地址是空的,所以不会请求通过代理,可以手工添加,方法为:ipset -A setmefree ip/mask
      然后 ipset list 就可以看到了,但这个方法还是很不智能,所以要配合 dnsmasq 来自动添加 IP 地址到池中。

    • 具体方法:

      从官网下载 dnsmasq 源码包并安装,不能直接 yum 安装,因为 yum 装的不会支持 ipset
      编写文档时 dnsmasq 的版本是:dnsmasq-2.72.tar.gz 如无重大更新,请下载最新版本。

      1
      tar -zxf dnsmasq-2.72.tar.gz; cd dnsmasq-2.72

      安装方法在此文件夹的 setup.html 中,也就是直接 make install ,
      会把程序安装到 /usr/local/sbin/dnsmasq ,然后 cp dnsmasq.conf.example /etc/dnsmasq.conf;
      直接执行 dnsmasq 就可以直接启动,配置文件读取 /etc/dnsmasq.conf
      配置文件中打开并指定文件 conf-file=/etc/dnsmasq.d/xxx.conf
      修改 xxx.conf 内容为:

      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
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      #Google and Youtube
      server=/.google.com/208.67.222.222#443
      server=/.google.com.hk/208.67.222.222#443
      server=/.gstatic.com/208.67.222.222#443
      server=/.ggpht.com/208.67.222.222#443
      server=/.googleusercontent.com/208.67.222.222#443
      server=/.appspot.com/208.67.222.222#443
      server=/.googlecode.com/208.67.222.222#443
      server=/.googleapis.com/208.67.222.222#443
      server=/.gmail.com/208.67.222.222#443
      server=/.google-analytics.com/208.67.222.222#443
      server=/.youtube.com/208.67.222.222#443
      server=/.googlevideo.com/208.67.222.222#443
      server=/.youtube-nocookie.com/208.67.222.222#443
      server=/.ytimg.com/208.67.222.222#443
      server=/.blogspot.com/208.67.222.222#443
      server=/.blogger.com/208.67.222.222#443

      #FaceBook
      server=/.facebook.com/208.67.222.222#443
      server=/.thefacebook.com/208.67.222.222#443
      server=/.facebook.net/208.67.222.222#443
      server=/.fbcdn.net/208.67.222.222#443
      server=/.akamaihd.net/208.67.222.222#443

      #Twitter
      server=/.twitter.com/208.67.222.222#443
      server=/.t.co/208.67.222.222#443
      server=/.bitly.com/208.67.222.222#443
      server=/.twimg.com/208.67.222.222#443
      server=/.tinypic.com/208.67.222.222#443
      server=/.yfrog.com/208.67.222.222#443

      #Dropbox
      server=/.dropbox.com/208.67.222.222#443

      #1024
      server=/.t66y.com/208.67.222.222#443

      #shadowsocks.org
      server=/.shadowsocks.org/208.67.222.222#443

      #btdigg
      server=/.btdigg.org/208.67.222.222#443

      #sf.net
      server=/.sourceforge.net/208.67.222.222#443

      #feedly
      server=/.feedly.com/208.67.222.222#443

      # Here Comes The ipset

      #Google and Youtube
      ipset=/.google.com/setmefree
      ipset=/.google.com.hk/setmefree
      ipset=/.gstatic.com/setmefree
      ipset=/.ggpht.com/setmefree
      ipset=/.googleusercontent.com/setmefree
      ipset=/.appspot.com/setmefree
      ipset=/.googlecode.com/setmefree
      ipset=/.googleapis.com/setmefree
      ipset=/.gmail.com/setmefree
      ipset=/.google-analytics.com/setmefree
      ipset=/.youtube.com/setmefree
      ipset=/.googlevideo.com/setmefree
      ipset=/.youtube-nocookie.com/setmefree
      ipset=/.ytimg.com/setmefree
      ipset=/.blogspot.com/setmefree
      ipset=/.blogger.com/setmefree

      #FaceBook
      ipset=/.facebook.com/setmefree
      ipset=/.thefacebook.com/setmefree
      ipset=/.facebook.net/setmefree
      ipset=/.fbcdn.net/setmefree
      ipset=/.akamaihd.net/setmefree

      #Twitter
      ipset=/.twitter.com/setmefree
      ipset=/.t.co/setmefree
      ipset=/.bitly.com/setmefree
      ipset=/.twimg.com/setmefree
      ipset=/.tinypic.com/setmefree
      ipset=/.yfrog.com/setmefree

      #Dropbox
      ipset=/.dropbox.com/setmefree

      #1024
      ipset=/.t66y.com/setmefree

      #shadowsocks.org
      ipset=/.shadowsocks.org/setmefree

      #btdigg
      ipset=/.btdigg.org/setmefree

      #sf.net
      ipset=/.sourceforge.net/setmefree

      #feedly
      ipset=/.feedly.com/setmefree

      注意 server=ipset= 是一一对应的,意思就是通过 dnsmasq 解析出来的 IP 写到地址池 (setmefree) 中。

      启动 dnsmasq,当有访问的时候 ipset list 才会显示出地址,此时访问此列表中的地址的 80 443 端口的语法就会通过代理了。

  • 注意事项

    • xxx.conf 中使用的 dns 必须是无污染的,也就是没有被强制解析到错误的地址,208.67.222.222Opendns
      支持使用非标准端口(443,5353),据说不稳定,当不稳定的时候访问没有在列表中的域名时会不能解析出地址,
      所以还可以在代理服务器上安装另外一个 dnsmasq,设置缓存大一点(cache-size=1000000),
      并通过设置 resolv-file=/etc/dnsmasq.resolv.conf 中的 opendns 来解析国外 IP
      网关服务器再使用代理服务器上的 dns 来解析,这样如果 opendns 如果不稳定的时候还可以使用代理服务器上的 dns 缓存来解析。

    • 代理服务器上安装 dnsmasq 方法一致,只是配置不同:

      1
      2
      3
      4
      cache-size=1000000
      resolv-file=/etc/dnsmasq.resolv.conf
      # cat /etc/dnsmasq.resolv.conf
      # nameserver 208.67.222.222 # 但默认是使用53端口,请自行google如何使用443端口来查询
    • ipset list 中的地址是不会自动删除的,所以最好定期执行 ipset flush setmefree 来清空 setmefree 中的 IP以保证都是正常的。

    • 网关服务器上还可以安装 squid 正向代理。

  • 至此配置完成

如果对你有所帮助,请点击右上角的 Star