2013年2月2日星期六

Linode Vps 上,在CentOS操作系统中安装 PPTP VPN 服务器

现在大多数VPS服务器都位于国外,因此PPTP服务器可以用来搭建一个比较实用的代理服务器。PPTP服务需要用到特定的Linux内核技术,因此绝大多数OpenVZ架构的VPS都不能配置PPTP(可以用OPENVPN代替),但几乎所有的XEN或KVM架构的VPS都能正常安装。本文将以XEN架构的CentOS系统下安装PPTP服务为例进行讲解。

1、准备环境

PPTPD要求Linux内核支持mppe,一般来说CentOS安装时已经包含了;下面安装ppp与iptables:
1yum install perl ppp iptables

2、安装PPTPD

对于32位CentOS,执行
1wget http://acelnmp.googlecode.com/files/pptpd-1.3.4-1.rhel5.1.i386.rpm
2rpm -ivh pptpd-1.3.4-1.rhel5.1.i386.rpm
对于64位CentOS,执行
1wget http://acelnmp.googlecode.com/files/pptpd-1.3.4-1.rhel5.1.x86_64.rpm
2rpm -ivh pptpd-1.3.4-1.rhel5.1.x86_64.rpm

3、修改配置

编辑PPTP配置文件 /etc/ppp/options.pptpd 如内容下:
01name pptpd
02refuse-pap
03refuse-chap
04refuse-mschap
05require-mschap-v2
06require-mppe-128
07proxyarp
08lock
09nobsdcomp
10novj
11novjccomp
12nologfd
13idle 2592000
14ms-dns 8.8.8.8
15ms-dns 8.8.4.4
编辑配置文件 /etc/pptpd.conf ,内容如下:
1option /etc/ppp/options.pptpd
2logwtmp
3localip 192.168.254.1
4remoteip 192.168.254.100-254
* 其中localip与remoteip定义了客户端连接VPN服务器后被分配到的内网IP地址,可根据需要自己修改。
现在对用户认证文件 /etc/ppp/chap-secrets 进行配置,内容如下:
1testuser pptpd testpwd *
* testuser、testpwd对应修改为自己希望的VPN登录用户名和密码
将 /etc/sysctl.conf 文件中net.ipv4.ip_forward设置为 1 (如果没有,则按照格式新建一行):
1net.ipv4.ip_forward = 1
保存退出。执行
1/sbin/sysctl -p
使之生效。

4、设置iptables转发

1/etc/init.d/iptables start
2/sbin/iptables -t nat -A POSTROUTING -o eth0 -s 192.168.254.0/24 -j MASQUERADE
3/etc/init.d/iptables save
4/etc/init.d/iptables restart
* 注意,上面的192.168.254.0应该与之前设置的网段对应。



可能会出现以下的错误提示
Flushing firewall rules:                                   [  OK  ]
Setting chains to policy ACCEPT: security raw nat mangle fi[FAILED]
Unloading iptables modules:                                [  OK  ]
Applying iptables firewall rules:                          [  OK  ]
Loading additional iptables modules: ip_conntrack_netbios_n[FAILED]
#这两个问题主要是iptables版本和内核对不上导致的,据我所知,linode使用的是自己修改过的内核.
#第一个问题的修复需打开文件/etc/init.d/iptables,删除所有内容,并替换为以下内容。





#!/bin/sh
#
# iptables        Start iptables firewall
#
# chkconfig: 2345 08 92
# description:        Starts, stops and saves iptables firewall
#
# config: /etc/sysconfig/iptables
# config: /etc/sysconfig/iptables-config

# Source function library.
. /etc/init.d/functions

IPTABLES=iptables
IPTABLES_DATA=/etc/sysconfig/$IPTABLES
IPTABLES_CONFIG=/etc/sysconfig/${IPTABLES}-config
IPV=${IPTABLES%tables} # ip for ipv4 | ip6 for ipv6
PROC_IPTABLES_NAMES=/proc/net/${IPV}_tables_names
VAR_SUBSYS_IPTABLES=/var/lock/subsys/$IPTABLES

if [ ! -x /sbin/$IPTABLES ]; then
    echo -n $"/sbin/$IPTABLES does not exist."; warning; echo
    exit 0
fi

if lsmod 2>/dev/null | grep -q ipchains ; then
    echo -n $"ipchains and $IPTABLES can not be used together."; warning; echo
    exit 1
fi

# Old or new modutils
/sbin/modprobe --version 2>&1 | grep -q module-init-tools \
    && NEW_MODUTILS=1 \
    || NEW_MODUTILS=0

# Default firewall configuration:
IPTABLES_MODULES=""
IPTABLES_MODULES_UNLOAD="yes"
IPTABLES_SAVE_ON_STOP="no"
IPTABLES_SAVE_ON_RESTART="no"
IPTABLES_SAVE_COUNTER="no"
IPTABLES_STATUS_NUMERIC="yes"

# Load firewall configuration.
[ -f "$IPTABLES_CONFIG" ] && . "$IPTABLES_CONFIG"

rmmod_r() {
    # Unload module with all referring modules.
    # At first all referring modules will be unloaded, then the module itself.
    local mod=$1
    local ret=0
    local ref=

    # Get referring modules.
    # New modutils have another output format.
    [ $NEW_MODUTILS = 1 ] \
        && ref=`lsmod | awk "/^${mod}/ { print \\\$4; }" | tr ',' ' '` \
        || ref=`lsmod | grep ^${mod} | cut -d "[" -s -f 2 | cut -d "]" -s -f 1`

    # recursive call for all referring modules
    for i in $ref; do
        rmmod_r $i
        let ret+=$?;
    done

    # Unload module.
    # The extra test is for 2.6: The module might have autocleaned,
    # after all referring modules are unloaded.
    if grep -q "^${mod}" /proc/modules ; then
        modprobe -r $mod > /dev/null 2>&1
        let ret+=$?;
    fi

    return $ret
}

flush_n_delete() {
    # Flush firewall rules and delete chains.
    [ -e "$PROC_IPTABLES_NAMES" ] || return 1

    # Check if firewall is configured (has tables)
    tables=`cat $PROC_IPTABLES_NAMES 2>/dev/null`
    [ -z "$tables" ] && return 1

    echo -n $"Flushing firewall rules: "
    ret=0
    # For all tables
    for i in $tables; do
        # Flush firewall rules.
        $IPTABLES -t $i -F;
        let ret+=$?;

        # Delete firewall chains.
        $IPTABLES -t $i -X;
        let ret+=$?;

        # Set counter to zero.
        $IPTABLES -t $i -Z;
        let ret+=$?;
    done

    [ $ret -eq 0 ] && success || failure
    echo
    return $ret
}

set_policy() {
    # Set policy for configured tables.
    policy=$1

    # Check if iptable module is loaded
    [ ! -e "$PROC_IPTABLES_NAMES" ] && return 1

    # Check if firewall is configured (has tables)
    tables=`cat $PROC_IPTABLES_NAMES 2>/dev/null`
    [ -z "$tables" ] && return 1

    echo -n $"Setting chains to policy $policy: "
    ret=0
    for i in $tables; do
        echo -n "$i "
        case "$i" in
           security)
                    $IPTABLES -t security -P INPUT $policy \
                    && $IPTABLES -t security -P OUTPUT $policy \
                    && $IPTABLES -t security -P FORWARD $policy \
                   || let ret+=1
                ;;
            raw)
                $IPTABLES -t raw -P PREROUTING $policy \
                    && $IPTABLES -t raw -P OUTPUT $policy \
                    || let ret+=1
                ;;
            filter)
                $IPTABLES -t filter -P INPUT $policy \
                    && $IPTABLES -t filter -P OUTPUT $policy \
                    && $IPTABLES -t filter -P FORWARD $policy \
                    || let ret+=1
                ;;
            nat)
                $IPTABLES -t nat -P PREROUTING $policy \
                    && $IPTABLES -t nat -P POSTROUTING $policy \
                    && $IPTABLES -t nat -P OUTPUT $policy \
                    || let ret+=1
                ;;
            mangle)
                $IPTABLES -t mangle -P PREROUTING $policy \
                    && $IPTABLES -t mangle -P POSTROUTING $policy \
                    && $IPTABLES -t mangle -P INPUT $policy \
                    && $IPTABLES -t mangle -P OUTPUT $policy \
                    && $IPTABLES -t mangle -P FORWARD $policy \
                    || let ret+=1
                ;;
            *)
                let ret+=1
                ;;
        esac
    done

    [ $ret -eq 0 ] && success || failure
    echo
    return $ret
}

start() {
    # Do not start if there is no config file.
    [ -f "$IPTABLES_DATA" ] || return 1

    echo -n $"Applying $IPTABLES firewall rules: "

    OPT=
    [ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c"

    $IPTABLES-restore $OPT $IPTABLES_DATA
    if [ $? -eq 0 ]; then
        success; echo
    else
        failure; echo; return 1
    fi
   
    # Load additional modules (helpers)
    if [ -n "$IPTABLES_MODULES" ]; then
        echo -n $"Loading additional $IPTABLES modules: "
        ret=0
        for mod in $IPTABLES_MODULES; do
            echo -n "$mod "
            modprobe $mod > /dev/null 2>&1
            let ret+=$?;
        done
        [ $ret -eq 0 ] && success || failure
        echo
    fi
   
    touch $VAR_SUBSYS_IPTABLES
    return $ret
}

stop() {
    # Do not stop if iptables module is not loaded.
    [ -e "$PROC_IPTABLES_NAMES" ] || return 1

    flush_n_delete
    set_policy ACCEPT
   
    if [ "x$IPTABLES_MODULES_UNLOAD" = "xyes" ]; then
        echo -n $"Unloading $IPTABLES modules: "
        ret=0
        rmmod_r ${IPV}_tables
        let ret+=$?;
        rmmod_r ${IPV}_conntrack
        let ret+=$?;
        [ $ret -eq 0 ] && success || failure
        echo
    fi
   
    rm -f $VAR_SUBSYS_IPTABLES
    return $ret
}

save() {
    # Check if iptable module is loaded
    [ ! -e "$PROC_IPTABLES_NAMES" ] && return 1

    # Check if firewall is configured (has tables)
    tables=`cat $PROC_IPTABLES_NAMES 2>/dev/null`
    [ -z "$tables" ] && return 1

    echo -n $"Saving firewall rules to $IPTABLES_DATA: "

    OPT=
    [ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c"

    ret=0
    TMP_FILE=`/bin/mktemp -q /tmp/$IPTABLES.XXXXXX` \
        && chmod 600 "$TMP_FILE" \
        && $IPTABLES-save $OPT > $TMP_FILE 2>/dev/null \
        && size=`stat -c '%s' $TMP_FILE` && [ $size -gt 0 ] \
        || ret=1
    if [ $ret -eq 0 ]; then
        if [ -e $IPTABLES_DATA ]; then
            cp -f $IPTABLES_DATA $IPTABLES_DATA.save \
                && chmod 600 $IPTABLES_DATA.save \
                || ret=1
        fi
        if [ $ret -eq 0 ]; then
            cp -f $TMP_FILE $IPTABLES_DATA \
                && chmod 600 $IPTABLES_DATA \
                || ret=1
        fi
    fi
    [ $ret -eq 0 ] && success || failure
    echo
    rm -f $TMP_FILE
    return $ret
}

status() {
    tables=`cat $PROC_IPTABLES_NAMES 2>/dev/null`

    # Do not print status if lockfile is missing and iptables modules are not
    # loaded.
    # Check if iptable module is loaded
    if [ ! -f "$VAR_SUBSYS_IPTABLES" -a -z "$tables" ]; then
        echo $"Firewall is stopped."
        return 1
    fi

    # Check if firewall is configured (has tables)
    if [ ! -e "$PROC_IPTABLES_NAMES" ]; then
        echo $"Firewall is not configured. "
        return 1
    fi
    if [ -z "$tables" ]; then
        echo $"Firewall is not configured. "
        return 1
    fi

    NUM=
    [ "x$IPTABLES_STATUS_NUMERIC" = "xyes" ] && NUM="-n"
    VERBOSE=
    [ "x$IPTABLES_STATUS_VERBOSE" = "xyes" ] && VERBOSE="--verbose"
    COUNT=
    [ "x$IPTABLES_STATUS_LINENUMBERS" = "xyes" ] && COUNT="--line-numbers"

    for table in $tables; do
        echo $"Table: $table"
        $IPTABLES -t $table --list $NUM $VERBOSE $COUNT && echo
    done

    return 0
}

restart() {
    [ "x$IPTABLES_SAVE_ON_RESTART" = "xyes" ] && save
    stop
    start
}

case "$1" in
    start)
        stop
        start
        RETVAL=$?
        ;;
    stop)
        [ "x$IPTABLES_SAVE_ON_STOP" = "xyes" ] && save
        stop
        RETVAL=$?
        ;;
    restart)
        restart
        RETVAL=$?
        ;;
    condrestart)
        [ -e "$VAR_SUBSYS_IPTABLES" ] && restart
        ;;
    status)
        status
        RETVAL=$?
        ;;
    panic)
        flush_n_delete
        set_policy DROP
        RETVAL=$?
        ;;
    save)
        save
        RETVAL=$?
        ;;
    *)
        echo $"Usage: $0 {start|stop|restart|condrestart|status|panic|save}"
        exit 1
        ;;
esac





#第二个问题的修复需要修改/etc/sysconfig/iptables-config配置,关闭ip_conntrack_netbios_ns模块,如下
IPTABLES_MODULES=""
IPTABLES_MODULES_UNLOAD="no"

5、设置开机启动

1chkconfig pptpd on
2chkconfig iptables on
重启计算机即可进行连接,并且能够正常上网。
如果重启服务器后,无法连接VPN,首先检查服务器的PPTP服务1723端口是否已打开(注意设置防火墙允许此端口);如果可以连接VPN,但是无法正常上网,则检查iptables是否正常转发。

没有评论:

发表评论