如何在Ubuntu 12.04 LTS 上安装L2TP Server

| 评论

安装必要组件

1
sudo apt-get install xl2tpd openswan ppp

IPSec / Openswan

  • 拷贝下面内容到 /etc/ipsec.conf, 并把其中的x.x.x.x替换为你服务器的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
32
33
34
35
config setup
    nat_traversal=yes
    virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:!10.152.2.0/24
    #contains the networks that are allowed as subnet= for the remote client. In other words, the address ranges that may live behind a NAT router through which a client connects.
    oe=off
    protostack=netkey

conn L2TP-PSK-NAT
    rightsubnet=vhost:%priv
    also=L2TP-PSK-noNAT

conn L2TP-PSK-noNAT
    authby=secret
    pfs=no
    auto=add
    keyingtries=3
    rekey=no
    # Apple iOS doesn't send delete notify so we need dead peer detection
    # to detect vanishing clients
    dpddelay=30
    dpdtimeout=120
    dpdaction=clear
    # Set ikelifetime and keylife to same defaults windows has
    ikelifetime=8h
    keylife=1h
    type=transport
    # Replace IP address with your local IP (private, behind NAT IP is okay as well)
    left=x.x.x.x
    # For updated Windows 2000/XP clients,
    # to support old clients as well, use leftprotoport=17/%any
    leftprotoport=17/1701
    right=%any
    rightprotoport=17/%any
    #force all to be nat'ed. because of iOS
    forceencaps=yes
  • 拷贝下面内容到 /etc/ipsec.secrets, 并把其中的x.x.x.x替换为你服务器的ip
1
x.x.x.x   %any:  PSK "somegoodpassword"
  • 开启ipsec服务
1
/etc/init.d/ipsec start
  • 执行下面脚本
1
2
3
4
5
for each in /proc/sys/net/ipv4/conf/*
do
echo 0 > $each/accept_redirects
echo 0 > $each/send_redirects
done
  • 验证ipsec服务
1
sudo ipsec verify

不能出现任何错误

1
2
3
4
5
6
7
8
9
10
11
12
Checking your system to see if IPsec got installed and started correctly:
Version check and ipsec on-path                                 [OK]
Linux Openswan U2.6.28/K2.6.32-32-generic-pae (netkey)
Checking for IPsec support in kernel                            [OK]
NETKEY detected, testing for disabled ICMP send_redirects       [OK]
NETKEY detected, testing for disabled ICMP accept_redirects     [OK]
Checking that pluto is running                                  [OK]
Pluto listening for IKE on udp 500                              [OK]
Pluto listening for NAT-T on udp 4500                           [OK]
Checking for 'ip' command                                       [OK]
Checking for 'iptables' command                                 [OK]
Opportunistic Encryption Support                                [DISABLED]
  • 创建/etc/init.d/ipsec.vpn的启动脚本
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
case "$1" in
  start)
echo "Starting my Ipsec VPN"
iptables  -t nat   -A POSTROUTING -o eth0 -s 10.152.2.0/24 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
for each in /proc/sys/net/ipv4/conf/*
do
    echo 0 > $each/accept_redirects
    echo 0 > $each/send_redirects
done
/etc/init.d/ipsec start
/etc/init.d/xl2tpd start
;;
stop)
echo "Stopping my Ipsec VPN"
iptables --table nat --flush
echo 0 > /proc/sys/net/ipv4/ip_forward
/etc/init.d/ipsec stop
/etc/init.d/xl2tpd stop
;;
restart)
echo "Restarting my Ipsec VPN"
iptables  -t nat   -A POSTROUTING -o eth0 -s 10.152.2.0/24 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
for each in /proc/sys/net/ipv4/conf/*
do
    echo 0 > $each/accept_redirects
    echo 0 > $each/send_redirects
done
/etc/init.d/ipsec restart
/etc/init.d/xl2tpd restart

;;
  *)
 echo "Usage: /etc/init.d/ipsec.vpn  {start|stop|restart}"
 exit 1
  ;;
esac

开启执行权限

1
sudo chmod +x /etc/init.d/ipsec.vpn

关闭默认的ipsec服务

1
sudo update-rc.d -f ipsec remove

添加刚刚创建的服务

1
sudo update-rc.d ipsec.vpn defaults

L2TP

  • 拷贝下面内容到/etc/xl2tpd/xl2tpd.conf
1
2
3
4
5
6
7
8
9
10
11
12
[global]
ipsec saref = no

[lns default]
ip range = 10.152.2.2-10.152.2.254
local ip = 10.152.2.1
require chap = yes
refuse pap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.xl2tpd
length bit = yes
  • /etc/xl2tpd/l2tp-secrets中创建验证字符串
1
* * exampleforchallengestring
  • 拷贝下面内容到/etc/ppp/options.xl2tpd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
refuse-mschap-v2
refuse-mschap
ms-dns 8.8.8.8
ms-dns 8.8.4.4
asyncmap 0
auth
crtscts
idle 1800
mtu 1200
mru 1200
lock
hide-password
local
#debug
name l2tpd
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4

添加用户

- 编辑文件/etc/ppp/chap-secrets这里和pptp是同一个文件

1
2
user1 l2tpd chooseagoodpassword *
user2 * chooseagoodpassword *

开启转发,配置过pptp则可跳过

- 编辑文件/etc/sysctl.conf

1
net.ipv4.ip_forward=1

执行

1
sysctl -p

开启服务

1
sudo /etc/init.d/ipsec.vpn restart

开启防火墙端口,如果使用防火墙

1
2
3
4
5
L2TP
———————————
UDP:500    (isakmp)
UDP:4500   (nat-t)
UDP:1701   (l2tp)

Mac连接

  • 打开network preferences创建l2tp类型的vpn,填入服务器ip,用户名
  • 验证里面password填上面设置的somegoodpassword
  • shared secret 填 exampleforchallengestring
  • iOS设备同理

    Winter is coming

    来源: L2TPServer, VPN端口号:PPTP、L2TP

Swift学习笔记-2-函数和闭包

| 评论

使用func定义函数,通过函数名和参数列表来调用函数, 使用->分割参数列表和返回类型

1
2
3
4
func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)"
}
greet("Bob", "Tuesday")

使用元组(tuple)返回多个值

1
2
3
4
5
func getGasPrices -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
// 还不知道如何获得返回值,会补上
getGasPrices()

函数的变长参数会保存在指定名字的数组中

1
2
3
4
5
6
7
8
9
10
func sumOf(numbers:Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }

    return sum
}
sumOf()            // 0
sumOf(42, 597, 12) // 651

可以使用嵌套函数,嵌套的函数可以访问它所嵌入函数中所的声明的变量。 函数太长或是太复杂的情况下可以使用嵌套函数来组织代码。

1
2
3
4
5
6
7
8
9
10
func returnFifteen() -> Int {
    var y = 0
    func add() {
        y += 5
    }
    add()

    return y
}
returnFifteen() // 5

函数是一等类型,这意味着可以把函数当做另一个函数的返回值

1
2
3
4
5
6
7
8
9
10
// 返回类型的解释是:返回 一个接受整形参数返回整形的函数
func makeIncrementer() -> (Int -> Int) {
    func addOne(number:Int) ->Int {
        return 1 + number
    }

    return addOne
}
var increment = makeIncrementer()
increment(7) // 8

也意味着函数可以作为另一个函数的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func hasAnyMathces(list:Int[], condition:Int -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}

func lessThanTen(number:Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMathces(numbers, lessThanTen) // true

函数是闭包的特例,闭包没有名字,使用花括号({})包围, 使用in来分割参数列表返回类型与主体

1
2
3
4
5
6
7
...
numbers.map({
    (number:Int) -> Int in
    let result = 3 * number
    return result
    })
// [60, 57, 21, 36]

有几个方法可以简化闭包,当闭包的类型是已知时 (如:委托(delegate)的回调(callback)),可以省略参数的类型, 返回类型,返回语句。而返回值隐含的包含在闭包唯一的语句之中

1
2
// [60, 57, 21, 36]
numbers.map({ number in 3 * number })

使用参数的序号代替参数名,即可写出超短的闭包, 闭包可以作为函数的最后一个参数

1
sort([1, 5, 3, 12, 2]) { $0 > $1 } // [12, 5, 3, 2, 1]

Swift学习笔记-1-流程控制

| 评论

条件语句使用ifswitch,循环使用for-inforwhiledo-while, 条件变量和循环变量的圆括号可选,条件体和循环体必须有花括号。

1
2
3
4
5
6
7
8
9
10
11
12
let individualScores = [75, 43, 103, 87, 12]

var teamScore = 0

for score in individualScores {
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
teamScore // 11

if语句中,条件必须是布尔表达式,也就是说if socre { ... }是错误的, 没有隐含的0比较.

一个变量可能没有值的时候,iflet可以一起使用,这些值通过 可选值(optional value)表示。一个可选值要么包含一个值,要么是nil, 在类型后面加问号(?)就可以把一个值标记为可选值

1
2
3
4
5
6
7
8
9
10
11
var optionalString: String? = "Hello"
optionalString == nil

var optionalName: String? = "John Appleseed"
//var optionalName: String? = nil
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
} else {
    greeting = "Hello, world"
}

可选值为nil条件的结果是false,用let声明的name的作用域 仅在if-else结构中

switch可以使用任何种类的比较数据,而不只是整型数值和相等的比较

1
2
3
4
5
6
7
8
9
10
11
let vegetable = "red pepper"
switch vegetable {
case "celery":
    let vegetableComment = "Add some raisins and make ants on a log."
case "cucumber", "watercress":
    let vegetableComment = "That would make a good tea sandwich"
case let x where x.hasSuffix("pepper"):
    let vegetableComment = "Is it a spicy \(x)?"
default:
    let vegetableComment = "Everything tastes good in soup"
}

代码执行时如果switch case匹配,switch就会退出,不会执行后面的case, 所以不必要在每个case结束之后加入break 要注意的是在switch必须要有一个default,否则会报错

使用键值对在for-in遍历字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]

var largest = 0;
var largestKind = "";
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
            largestKind = kind
        }
    }
}
largest      // 25
largestKind  // Square

while来执行一段代码直到条件改变,条件可以放在循环的最后(do-while), 来保证循环至少执行一次

1
2
3
4
5
6
7
8
9
10
11
12
13
var n = 2
while n < 100 {
    n = n * 2
}

n // 128

var m = 2

do {
    m = m * 2
} while m < 100
m // 128

在循环中使用range..或是初始化,条件,增量的形式来获得索引

1
2
3
4
5
6
7
8
9
10
11
12
var firstForLoop = 0
for i in 0..3 {
    firstForLoop += i
}

firstForLoop // 3

var secondForLoop = 0
for var i = 0; i < 3; ++i {
    secondForLoop += 1
}
secondForLoop // 3

..排除最后一个值 ...包含最后一个值

Swift学习笔记-0

| 评论

Apple在昨天的WWDC上发布了新的语言Swift,非常值得一学, 主要用来做书The Swift Programming Language (iBooks)的笔记和一些自己的想法。

Hello,world不用载入其他的库,不需要main函数,不需要分号结尾

1
println("Hello, world")

var声明变量,用let声明常量, 编译器根据变量和常量的赋值推断其类型

1
2
3
var myVariable = 42
myVariable = 50
let myConstant = 42

也可以显式的指定类型

1
let explicitDouble: Double = 70

不能隐式改变类型,要显式改变

1
2
3
let label = "The width is"
let width = 94
let widthLabel = label + String(width)

\()内嵌字符串

1
2
3
4
let apples = 3
let oranges= 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

下面这点让我开始喜欢Swift,数组(array)和字典(dictionary) 统一使用[]创建

1
2
3
4
5
6
7
8
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water" // 这点可以看出Swift也是从0开始

var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

使用initializer syntax创建空数组和字典

1
2
3
4
let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()
// 说明Swift是强类型的,不像脚本语言可以装任意对象在数组和字典里面
// 字典的key只能使用 String,而不是任何对象

如果类型可以确定,使用[]创建并重新赋值数组,使用[:]创建并重新赋值字典。

1
shoppingList = [] // 已经去购物了,而且东西都买到了,也就是shopping置空

设计模式读书笔记-0

| 评论

专门查询了下购买《设计模式——可复用面向对象软件的基础 (双语版)》的订单,购买时间是2008年(2008-06-12)。开始了很多次, 每次都只看了开头就放弃了,这次打算好好看完。

终于在六一儿童节这天看完,看得还算轻松。 以后在设计中可以尝试使用了。 还好买的是双语版,因为要在短时间之内看完,所以选择先看中文的, 也许是因为这本书出的比较早,很多术语和现在的翻译很不一样,而且在 同一本书中,存在翻译不一致的问题,每每这个时候就只好参考下英文版了 (本人学渣)。

  • “针对接口编程,而不是针对实现编程”。
  • “优先使用对象组合,而不是类继承”。
  • 预见性,前段时间学车,教练就说,开车要有预见性,写程序也是一样, 面对需求的变化要有预见性,这也就是学习设计模式的意义。
  • 设计模式的使用不能是为了使用而使用,如果不能够让系统的设计更加完善和灵活 就没有必要使用。
  • 一个系统的设计可以先不用设计模式,然后通过设计模式重构。

以后会这里记录下使用的心得。

Shadowsocks Sock5 代理配置-服务端篇

| 评论

0.废话不说,直接上,哦不是,直接用ssh连上服务器
1.检查python的版本,需要2.6或者2.7,3.0以上没有测试过

1
2
python --version
# Python 2.7.3

2.安装所需要的python库以及pip

1
2
# 之前可以先 sudo apt-get update
sudo apt-get install python-gevent python-m2crypto python-pip

3.安装shadowsocks

1
sudo pip install shadowsocks

4.用你喜欢的编辑器创建config.json

1
2
3
4
5
6
7
8
{
    "server":"你的服务器ip", // 你的服务器ip
    "server_port":8388,    // shadowsocks监听的端口,建议修改,如果服务器有防火墙记得打洞
    "local_port":1080,     // 服务端不重要
    "password":"barfoo!",  // 加密的密码
    "timeout":600,
    "method":"aes-256-cfb" // 加密方式,前面已经安装了python-m2crypto,这里可以选择这个
}

无注释版

1
2
3
4
5
6
7
8
{
    "server":"你的服务器ip",
    "server_port":8388,
    "local_port":1080,
    "password":"barfoo!",
    "timeout":600,
    "method":"aes-256-cfb"
}

5.开个screen,开启shadowsocks

1
2
3
screen -S s
# 注意有3个s
ssserver -c config.json

Ruby 小技巧

| 评论

Iterrator 有时需要index,那就加入with_index,如下

1
2
3
4
f = File.open("testfile")
f.each.with_index do |line, index|
  puts "Line #{index} is: #{line}"
end

在Rails的migration中添加字段(add_column)option的limit说设置的值 是添加字段类型的默认值,limit就不会出现在db/schema.rb中的相应位置。

为什么我痛恨Mac

| 评论

我爱Mac,但Mac满满的都是槽点 1. 我的是rMBP,USB接口少的可怜,才有两个,外接一个机械键盘,外接一个鼠标就没有了(不要告诉用蓝牙的,我也知道)
2. 全局输入法切换,写代码的时候和朋友聊天,回到写代码的时候太难受,何况我用的还是vim(是我不懂Mac啊,改个设置就可以了啊)
3. 如果光标在输入框内捏合进入Launchpad是还是输入的光标而不是指针,会看不见
4. 玩游戏不过瘾啊不过瘾

我喜欢Mac的几个原因

| 评论

用了Mac还没有几天,就彻底的爱上Mac了
1. 电源线,非常柔软,不会硬邦邦的戳到改变Mac和插板的位置
2. 不用重启,就算重启,重启以后可以自动回到重启之前的状态
3. 不用关机,开机,盖上盖子就好,这个直接影响了我的习惯,原来用电脑的时候要先开机,然后去做别的事情 很久很久之后才能使用,关机也是。
4. TrackPad 我从来没有想过触摸板会这么好用,好用到可以完全不用鼠标了
5. 超级快,安装个Ubuntu的虚拟机只要5分钟windows只要6分钟
6. 终端和系统配合的特别好,这对于码农来说实在是太好了
7. 安静,平时使用的时候几乎听不到任何风扇的声音,话说我的大Y随便用用就好比的轰炸机飞过
8. 和iOS设备配合的特别好,iTunes似乎也没有那么难用了
9. 截图功能非常不错
10. 背光键盘,这让我在晚上能够关着灯使用Mac
11. 有超级好用的文档工具Dash
12. command+, 几乎是每个软件Preferences的快捷键
13. 不插电的情况下Safari中的插件不会自动运行。
14. 通知中心和免打扰,工作时不会受到打扰。
15. 字体,让我义无反顾。
16. 下载的zip可以自动解压。

使用through关联时访问关系的属性

| 评论

0.有下面三个 model 关联,使用 through 来简化对 Ownership 的访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class User < ActiveRecord::Base
  # association
  has_many :ownerships, dependent: :destroy
  has_many :shops, through: :ownerships
end

class Ownership < ActiveRecord::Base
  belongs_to :user
  belongs_to :shop
end

class Shop < ActiveRecord::Base
  # association
  has_one  :ownership, dependent: :destroy
  has_one  :user, through: :ownership
end

1.此时无法在Shop中在 after_create 来访问 ownership 的 user_id 属性,因为这时 owership 还未创建。当事务 commit 以后 owership 被创建,同时拥有 user_id 属性。这时就可以获得 user_id 从而进行相关操作

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
class Shop < ActiveRecord::Base
  after_commit :get_attr_after_destroy, on: [:destroy]
  after_commit :get_attr_after_create,  on: [:create]

  after_create :get_attr_in_after_create

  # association
  has_one  :ownership, dependent: :destroy
  has_one  :user, through: :ownership

  private
    def get_attr_after_destroy
      user_id = self.ownership.user_id
    end

    def get_attr_after_create
      user_id = self.ownership.user_id
    end

    def get_attr_in_after_create
      # self.ownership is nil
      # NoMethodError: undefined method `user_id' for nil:NilClass
      user_id = self.ownership.user_id
    end
end