• Archive by category "IT相关知识"

Blog Archives

在Ubuntu中安装Docker

Ubuntu实用工具系列文章,将介绍基于Linux ubuntu的各种工具软件的配置和使用。有些工具大家早已耳熟能详,有些工具经常用到但确依然陌生。我将记录我在使用操作系统时,安装及配置工具上面的一些方法,把使用心得记录下来也便于自己的以后查找和回忆。

关于作者:

  • 张丹, 程序员R,Nodejs,Java
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/linux-docker-install/

ubuntu-docker

前言

网上已经有很多介绍Docker安装的文章,自己的安装过程记录一下,为了博客文章结构的连贯性,为写下一篇R和Docker的相遇做为环境基础,同时也给自己一个备忘。

目录

  1. Docker是什么?
  2. 在Linux Ubuntu中安装Docker
  3. Docker镜像仓库
  4. 制作自己的Docker镜像
  5. 上传Docker镜像到公共仓库

1. Docker是什么?

在互联网圈混,如果还不知道Docker你就out了。从2014年开始,docker技术在互联网技术中异军突起,2015-2016年很多公司已经对Docker开始大量研究和应用。

Docker是什么?Docker是一个开源的应用容器引擎,系统级的轻量虚拟化技术,为应用程序的自动化部署提供解决方案。

你可以快速创建一个容器,并在容器上开发和运行你们的应用程序,通过配置文件可以轻松实现应用程序的自动化安装、部署和升级。

Docker的优势

Docker倍受业界追捧,必然有它非常明显的优势和特点。

  • 轻量级资源:容器是在进程级别隔离,并使用宿主机的内核,而不需要虚拟化整个操作系统。不需要虚拟化和系统调用复杂的操作。因此节省了很大的额外开销。不需要额外的hypervisor(虚拟化技术)支持,不需要虚拟硬件,不需要额外完整的系统。
  • 可移植性:所需要的应用都在容器中,可以在任意一台docker主机上运行
  • 可预测性:宿主机和容器相互不关心对方都运行什么。只考虑所需的接口标准化。

再不动手把Docker用上,你就真的out了。

2. 在Linux Ubuntu中安装Docker

安装Docker只需3步,下载Docker, 安装Docker,检查Docker是否成功。

Docker目前支持主流的3种操作系统的Linux, Mac, Windows的环境,本文使用的Linux系统环境为:Linux Ubuntu 14.04.4 LTS 64bit。在Ubuntu中下载和安装Docker可以直接用apt-get搞定。

由于Docker在1.7.1以后的版本指定了自己的源,所以我们需要先在APT中配置Docker的源。

更新APT的源,安装https和ca证书的库,默认这2个库都已经装了。


~ sudo apt-get update
~ sudo apt-get install apt-transport-https ca-certificates

添加秘钥GPG到APT配置中。


~ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

增加Docker的源到/etc/apt/souces.list文件中,我的版本是14.04对应ubuntu-trusty。


~ sudo vi /etc/apt/sources.list

# 增加到最后一行
deb https://apt.dockerproject.org/repo ubuntu-trusty main

接下来,就可以用可以用apt-get直接安装Docker了。


~ sudo apt-get update
~ sudo apt-get install docker-engine

安装完成,默认会启动Docker。


# 检查docker服务
~ service docker status
docker start/running, process 10013

# 检查docker进行
~ ps -aux|grep docker
root     10013  0.0  1.0 424948 40584 ?        Ssl  22:29   0:00 /usr/bin/dockerd --raw-logs
root     10022  0.0  0.2 199680 10280 ?        Ssl  22:29   0:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --shimdocker-containerd-shim --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --runtime docker-runc

# 检查docker版本
~ sudo docker version
Client:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 05:22:43 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.1
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   23cf638
 Built:        Thu Aug 18 05:22:43 2016
 OS/Arch:      linux/amd64

检查Docker是否成功,运行hello-world。如果出现下面的信息,表示Docker引擎安装成功。


~ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c04b14da8d14: Pull complete 
Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

注意:我们在执行上面的命令的时候,经常会遇到一个错误。Cannot connect to the Docker daemon. Is the docker daemon running on this host?

比如,直接输入 docker run hello-world 命令。


~ docker run hello-world
docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.

这是由于权限的问题,docker默认和root权限绑定,如果不加sudo时则没有权限。

3. Docker镜像仓库

对于上面我们执行的docker run hello-world命令,是什么意思呢?

把3个词分开来看,docker代表docker程序,run代表命令,hello-world代表镜像。就是用docker启动hello-world镜像。由于我们刚装好的docker,本地并没有镜像,那么run的命令会对docker远端的仓库中,找到名叫hello-world的镜像,然后下载到本地,再运行。

Docker官方的镜像仓库访问地址:https://hub.docker.com/

我们可以在Docker官方的仓库中,搜索你感兴趣的系统、语言、技术框架等,有很多的技术都已经被docker化了。我们就可以很方便地用别人已经做好的容器,站在前人的基础上继续工作。

docker-repo

从列表中点开一项后,会有对这个镜像的详细介绍。比如,Ubuntu的镜像。

docker-repo2

如果我们想要下载这个镜像,只需要按照他的提示,在命令行输入 docker pull ubuntu 这样就行了。


~ sudo docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
2f0243478e1f: Pull complete 
d8909ae88469: Pull complete 
820f09abed29: Pull complete 
01193a8f3d88: Pull complete 
Digest: sha256:8e2324f2288c26e1393b63e680ee7844202391414dbd48497e9a4fd997cd3cbf
Status: Downloaded newer image for ubuntu:latest

下载好后镜像,会保存在本地的仓库中。查看本地的镜像。


~ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              f8d79ba03c00        2 weeks ago         126.4 MB
hello-world         latest              c54a2cc56cbb        7 weeks ago         1.848 kB

目前,有2个本地镜像,一个是hello-world,另一个是ubuntu。

4. 制作自己的Docker镜像

我们也可以制作自己的镜像,然后上传到官方的仓库中,让更多的人来使用。如果要制作自己的Docker镜像,你只需要写一个Dockerfile文件就行了。

下面我们创建一个能进行网络访问的Docker,从http://fens.me网站抓取最新8篇的文章列表,并打印到控制台。

docker-curl-fensme

创建项目目录


~ mkdir fensme && cd fensme

创建Dockerfile,依赖于上文中下载的ubuntu镜像,还要需要安装curl库用于网页抓取,同时用于jq库解析JSON数据。


~ vi Dockerfile

FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl jq
CMD curl http://api.fens.me/blogs/ | jq .[]

打包,创建名为fensme的镜像。


# 打包
~ sudo docker build -t fensme .

# 查看镜像列表
~ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
fensme              latest              41b68972b35a        4 minutes ago       182.8 MB
ubuntu              latest              f8d79ba03c00        2 weeks ago         126.4 MB
hello-world         latest              c54a2cc56cbb        7 weeks ago         1.848 kB

运行fensme的镜像,这样就实现了网站数据的抓取。


~ sudo docker run fensme
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1421  100  1421    0     0    715      0  0:00:01  0:00:01 --:--:--   715
{
  "title": "R语言解读自回归模型",
  "date": 20160819,
  "link": "http://blog.fens.me/r-ar/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/08/r-ar.png"
}
{
  "title": "R语言量化投资常用包总结",
  "date": 20160810,
  "link": "http://blog.fens.me/r-quant-packages/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/08/quant-packages.png"
}
{
  "title": "R语言跨界调用C++",
  "date": 20160801,
  "link": "http://blog.fens.me/r-cpp-rcpp",
  "img": "http://blog.fens.me/wp-content/uploads/2016/08/rcpp.png"
}
{
  "title": "R语言解读多元线性回归模型",
  "date": 20160727,
  "link": "http://blog.fens.me/r-multi-linear-regression/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/07/reg-multi-liner.png"
}
{
  "title": "R语言解读一元线性回归模型",
  "date": 20160725,
  "link": "http://blog.fens.me/r-linear-regression/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/07/reg-liner.png"
}
{
  "title": "R语言中文分词包jiebaR",
  "date": 20160721,
  "link": "http://blog.fens.me/r-word-jiebar/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/07/jiebaR.png"
}
{
  "title": "2016天善智能交流会第22场: R语言为量化而生",
  "date": 20160704,
  "link": "http://blog.fens.me/meeting-hellobi-20160701/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/07/meeting-hellobi.png"
}
{
  "title": "R语言为量化而生",
  "date": 20160703,
  "link": "http://blog.fens.me/r-finance/",
  "img": "http://blog.fens.me/wp-content/uploads/2016/07/r-finance.png"
}

这个例子,我们通过Docker封装了一个非常简单的爬虫,当你需要的时候启动它,把结果写到数据库中。当执行完任务,系统资源就释放了,你需要再为它考虑。

比较简单地就可以把一个技术或一个功能Docker化,从而构建出个性化的Docker。

5. 上传Docker镜像到公共仓库

最后一步,其实就是把我们做好的Docker镜像上传到官方的仓库中,让其他的人也可以使用。

首先需要去docker hub上面注册一个账号,然后登录进去。

docker-hub-login

在docker hub上,创建一个自己的仓库。

docker-hub-create

在本地操作系统,绑定docker hub的账号


~ sudo docker login --username=bsspirit --email=bsspirit@163.com
Flag --email has been deprecated, will be removed in 1.13.
Password: 
Login Succeeded

接下来,要你刚才创建的fensme的镜像加上命名空间,对应该docker hub上面镜像名bsspirit/fensme。


# 给fensme增加命名空间
~ sudo docker tag 8496b10e857a bsspirit/fensme:latest

~ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
bsspirit/fensme     latest              8496b10e857a        About a minute ago   182.8 MB
fensme              latest              8496b10e857a        15 minutes ago       182.8 MB
ubuntu              latest              f8d79ba03c00        2 weeks ago          126.4 MB
hello-world         latest              c54a2cc56cbb        7 weeks ago          1.848 kB

上传bsspirit/fensme镜像,然后你就可以在docker hub的网站上看到你自己的镜像了。


~ sudo docker push bsspirit/fensme
The push refers to a repository [docker.io/bsspirit/fensme]
d9c50c22842b: Pushed 
4699cbd1a947: Pushed 
2bed5b3ec49f: Pushed 
3834bde7e567: Pushed 
d8d865b23727: Pushed 
latest: digest: sha256:bfea736a92b6e602d6bbca867715b0e985f2e9bc3ea4a75b545d7e009e22ac2b size: 1362

打开docker hub网站,刷新页面。

docker-repo3

最后,如果其他人需要使用这个docker镜像,像最开始介绍的,直接下载运行就可以了。


~ sudo docker run bsspirit/fensme

通过上面的操作,我们就把Docker在Linux Ubuntu中的系统安装完成。

转载请注明出处:
http://blog.fens.me/linux-docker-install/

打赏作者

用阿里云配置VPN

操作系统实用工具系列文章,将介绍基于Linux ubuntu的各种工具软件的配置和使用。有些工具大家早已耳熟能详,有些工具经常用到但确依然陌生。我将记录我在使用操作系统时,安装及配置工具上面的一些方法,把使用心得记录下来也便于自己的以后查找和回忆。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/vpn-aliyun/

aliyun-vpn

前言

每次配置虚拟机的网络环境,都要花不少的时间,这次在阿里云上捣鼓VPN又出了岔子,VPN映射的网段和阿里云的虚拟机内网网段重叠了,而且阿里云自动做了路由,导致VPN路由失效。

本文将总结一下阿里云配置VPN的问题,估计自己以后也会经常回来翻看的。

目录

  1. 网络架构
  2. 遇到的问题
  3. 如何解决问题

1. 网络架构

要开发一个互联网应用,通常我们都需要购买服务器,部署自己应用然后托管到机房。对于刚起步的小公司来说,买服务器到托管到机房成本有点高,而且可能资源用不完,这时我们就有了一个更便宜的选择就是先租虚拟主机,阿里云就提供了这种服务。当然,和国外的主机服务商比阿里云还是很贵的,而且服务还有一些差距,但和国外的其他服务商比,也只能选阿里云了。

通常在阿里云租的虚拟主机,都会包括一个外网IP(121.x.x.x)和一个内网IP(10.x.x.x),外网IP主要面向互联网的访问,内网IP可以让内网的多台计算机通过内网进行通信。

接下来,我们会对应用进行分层,有用于数据存储的服务器(大硬盘),有用于计算的服务器(CPU密集型),有用于用户访问服务器(IO密集型)。另外,对于私密性比较高的数据或应用,我们通常用到VPN进行加密访问,从而保证传输过程的安全。

aliyun

我们一旦建立VPN连接,所有外网网络访问都将走VPN的加密通道,VPN通常只是小型私密网络,所以互联网的访问连接将会被切断。那么当互联网的访问被切掉到了,我们用Putty远程连接VPN的主机,也会访问不到了,这时就需要通过内网其他主机进行代理连接。比如,当Aliyun1打开VPN后,我们就不能直接通过Putty连接了,需要先用Putty登陆Aliyun2,再通过Aliyun2走内网登陆到Aliyun1。

对于虚拟主机来说,即使只租用一台服务器也可以实现VPN的连接。当服务器进行了VPN连接,你可以从宿主机管理控制台,对连接VPN的计算机进行操作。阿里云也提供了这个功能,可以通过网页直接登陆。

aliyun-2

2. 遇到的问题

上面我们介绍的,都是标准的VPN访问流程。那么,我其实遇到了一个问题,就是阿里云的内网IP网段是10.x.x.x,连接VPN生成的私密网络的网段也是10.x.x.x,这时就造成了IP网段冲突。每个网卡都需要配置IP地址,网关,子网掩码,DNS服务器等,如果内网和外网的网段或IP发生冲突,而且两边的网络服务都不能进行修改,那么就直接无解了。幸运的是,只是A类的地址冲突了,而且B类,C类,D类的地址没有冲突。那么,可以通过把网断进行不同的映射,配置网关和路由。

其实,发现上面的问题,也是花了一些时间的。

我们先看阿里云主机的默认网络配置。


~ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:16:3e:00:36:37
          inet addr:10.169.0.162  Bcast:10.169.7.255  Mask:255.255.248.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:109 errors:0 dropped:0 overruns:0 frame:0
          TX packets:43 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:9597 (9.5 KB)  TX bytes:6767 (6.7 KB)

eth1      Link encap:Ethernet  HWaddr 00:16:3e:00:3d:3b
          inet addr:121.41.77.206  Bcast:121.41.79.255  Mask:255.255.252.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2294 errors:0 dropped:0 overruns:0 frame:0
          TX packets:151 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:108919 (108.9 KB)  TX bytes:12624 (12.6 KB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

~ cat /etc/resolv.conf
options timeout:1 attempts:1 rotate
nameserver 10.202.72.118
nameserver 10.202.72.116

~ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         121.41.79.247   0.0.0.0         UG    0      0        0 eth1
10.0.0.0        10.169.7.247    255.0.0.0       UG    0      0        0 eth0
10.169.0.0      *               255.255.248.0   U     0      0        0 eth0
100.64.0.0      10.169.7.247    255.192.0.0     UG    0      0        0 eth0
121.41.76.0     *               255.255.252.0   U     0      0        0 eth1
172.16.0.0      10.169.7.247    255.240.0.0     UG    0      0        0 eth0

安装及配置VPNC


# 安装VPNC
~ apt-get install vpnc

# 配置文件
~ vi /etc/vpnc/default.conf

IPSec gateway xxx.com
IPSec ID xxx
IPSec obfuscated secret xxxxxxxxx
Xauth username xxx
Xauth password xxxxxx

启动VPN连接。


~ vpnc
Stopped Name Service Cache Daemon: nscd.
 * Starting Name Service Cache Daemon nscd                                             [ OK ]
VPNC started in background (pid: 1543)...

查看网站连接,会多出tun0的网卡,分配的IP地址为10.1.15.228。


~ ifconfig
eth0      Link encap:Ethernet  HWaddr 00:16:3e:00:36:37
          inet addr:10.169.0.162  Bcast:10.169.7.255  Mask:255.255.248.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1727 errors:0 dropped:0 overruns:0 frame:0
          TX packets:551 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:103050 (103.0 KB)  TX bytes:70120 (70.1 KB)

eth1      Link encap:Ethernet  HWaddr 00:16:3e:00:3d:3b
          inet addr:121.41.77.206  Bcast:121.41.79.255  Mask:255.255.252.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:128289 errors:0 dropped:0 overruns:0 frame:0
          TX packets:649 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:5435081 (5.4 MB)  TX bytes:82302 (82.3 KB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.1.15.228  P-t-P:10.1.15.228  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1412  Metric:1
          RX packets:40 errors:0 dropped:0 overruns:0 frame:0
          TX packets:82 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500
          RX bytes:3328 (3.3 KB)  TX bytes:11016 (11.0 KB)

通过情况下,这样的配置已经生效了,VPN也连接正常,但VPN网络确无法访问。


~ ping testvpn
ping: unknown host testvpn

第一感觉是DNS出问题了,查看DNS还是原来的内容,没有发生变化。


~ cat /etc/resolv.conf
options timeout:1 attempts:1 rotate
nameserver 10.202.72.118
nameserver 10.202.72.116

通常VPN连接的时候,都会配置一个新的DNS,那么我们把这个DNS设置成自动更新的。


~ dpkg-reconfigure resolvconf

同时,修改tail文件,设置一个更快速的阿里云DNS服务器。


vi /etc/resolvconf/resolv.conf.d/tail

nameserver 223.5.5.5
nameserver 223.6.6.6

断开VPN再重连接VPN


~ vpnc-disconnect
Terminating vpnc daemon (pid: 1543)

~ vpnc
Stopped Name Service Cache Daemon: nscd.
 * Starting Name Service Cache Daemon nscd                                             [ OK ]
VPNC started in background (pid: 2111)...

再次查看DNS的配置,我们看到/etc/resolv.conf已经会自动更新了。


cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 10.1.1.1
nameserver 10.1.1.2
search xxx.test.cn
nameserver 223.5.5.5
nameserver 223.6.6.6

但通过VPN网络还是无法访问。


~ ping testvpn
ping: unknown host testvpn

检查路由表


 route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         *               0.0.0.0         U     0      0        0 tun0
10.0.0.0        10.169.7.247    255.0.0.0       UG    0      0        0 eth0
10.1.15.0       *               255.255.255.0   U     0      0        0 tun0
10.169.0.0      *               255.255.248.0   U     0      0        0 eth0
100.64.0.0      10.169.7.247    255.192.0.0     UG    0      0        0 eth0
121.41.76.0     *               255.255.252.0   U     0      0        0 eth1
172.16.0.0      10.169.7.247    255.240.0.0     UG    0      0        0 eth0
vpn.test.com    121.41.79.247     255.255.255.255 UGH   0      0        0 eth1

这个时候就发现了,由VPN生成的10.1.15.0被强制使用了阿里云的10.0.0.0 的路由10.169.7.247,检查网卡配置文件/etc/network/interfaces。


~  cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth1
iface eth1 inet static
address 121.41.77.206
netmask 255.255.252.0
up route add -net 0.0.0.0 netmask 0.0.0.0 gw 121.41.79.247 dev eth1

auto eth0
iface eth0 inet static
address 10.169.0.162
netmask 255.255.248.0

up route add -net 172.16.0.0 netmask 255.240.0.0 gw 10.169.7.247 dev eth0
up route add -net 100.64.0.0 netmask 255.192.0.0 gw 10.169.7.247 dev eth0
up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.169.7.247 dev eth0

最后一行发现了问题。

up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.169.7.247 dev eth0

这个网段的10.0.0.0所有IP统一会使用10.169.7.247的网关,怪不得VPN始终不通,原来是阿里云服务器默认的配置造成的问题。

3. 如何解决问题

只要定位到了问题,解决就不难。

我们看到由于阿里云的内网是10.x.x.x的,我们的几台服务器也分别是10.168.x.x, 10.169.x.x, 10.200.x.x, 10.251.x.x,我估计它是从10.1.x.x到10.255.x.x都配置了网络,所以直接对A类网段进行了配置。通过VPN生成的IP为10.1.15.228,从B类网段开始刚好与阿里云租的机器不重合,那么我们重新定义阿里云的网段配置就行了,对B类网段做映射。

修改文件 /etc/network/interfaces。


~ vi /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth1
iface eth1 inet static
address 121.41.77.206
netmask 255.255.252.0
up route add -net 0.0.0.0 netmask 0.0.0.0 gw 121.41.79.247 dev eth1

auto eth0
iface eth0 inet static
address 10.169.0.162
netmask 255.255.248.0

up route add -net 172.16.0.0 netmask 255.240.0.0 gw 10.169.7.247 dev eth0
up route add -net 100.64.0.0 netmask 255.192.0.0 gw 10.169.7.247 dev eth0
#up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.169.7.247 dev eth0

up route add -net 10.200.0.0 netmask 255.255.0.0 gw 10.169.7.247 dev eth0
up route add -net 10.168.0.0 netmask 255.255.0.0 gw 10.169.7.247 dev eth0
up route add -net 10.169.0.0 netmask 255.255.0.0 gw 10.169.7.247 dev eth0
up route add -net 10.251.0.0 netmask 255.255.0.0 gw 10.169.7.247 dev eth0

重启网卡


~ /etc/init.d/networking restart

竟然是无效的命令,只能重启计算机了。


~ reboot

重启后,查看路由表。


~ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         121.41.79.247   0.0.0.0         UG    0      0        0 eth1
10.168.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
10.169.0.0      *               255.255.248.0   U     0      0        0 eth0
10.169.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
10.200.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
10.251.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
100.64.0.0      10.169.7.247    255.192.0.0     UG    0      0        0 eth0
121.41.76.0     *               255.255.252.0   U     0      0        0 eth1
172.16.0.0      10.169.7.247    255.240.0.0     UG    0      0        0 eth0

对B类网段的配置已经生效,已经去除了对A类10网段的配置。

连接VPN。


~ vpnc
Stopped Name Service Cache Daemon: nscd.
 * Starting Name Service Cache Daemon nscd                                             [ OK ]
VPNC started in background (pid: 1368)...

查看路由表


~ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         *               0.0.0.0         U     0      0        0 tun0
10.1.15.0       *               255.255.255.0   U     0      0        0 tun0
10.168.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
10.169.0.0      *               255.255.248.0   U     0      0        0 eth0
10.169.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
10.200.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
10.251.0.0      10.169.7.247    255.255.0.0     UG    0      0        0 eth0
100.64.0.0      10.169.7.247    255.192.0.0     UG    0      0        0 eth0
121.41.76.0     *               255.255.252.0   U     0      0        0 eth1
172.16.0.0      10.169.7.247    255.240.0.0     UG    0      0        0 eth0
vpn.test.com    121.41.79.247   255.255.255.255 UGH   0      0        0 eth1

10.1.15.0由VPN生成的IP,没有被强制路由。

连接VPN内网计算机


~ ping testvpn
PING testvpn.xxx.com.cn (10.1.1.13) 56(84) bytes of data.
64 bytes from testvpn.xxx.com.cn (10.1.1.13): icmp_seq=1 ttl=127 time=39.5 ms
64 bytes from testvpn.xxx.com.cn (10.1.1.13): icmp_seq=2 ttl=127 time=40.4 ms

终于访问正常了,这样就完成了,通过阿里云连接VPN服务的网络配置。

本文主要记录了网络调试的一系列操作,阿里云在方便易用的同时,也会有一些额外的问题,需要大家有更多的Linux使用经验,从而有能力解决各种的VM技术问题。

转载请注明出处:
http://blog.fens.me/vpn-aliyun/

打赏作者

那些年考的那些认证

架构师的信仰系列文章,主要介绍我对系统架构的理解,从我的视角描述各种软件应用系统的架构设计思想和实现思路。

从程序员开始,到架构师一路走来,经历过太多的系统和应用。做过手机游戏,写过编程工具;做过大型Web应用系统,写过公司内部CRM;做过SOA的系统集成,写过基于Hadoop的大数据工具;做过外包,做过电商,做过团购,做过支付,做过SNS,也做过移动SNS。以前只用Java,然后学了PHP,现在用R和Javascript。最后跳出IT圈,进入金融圈,研发量化交易软件。

架构设计就是定义一套完整的程序规范,坚持架构师的信仰,做自己想做的东西。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/architect-certification/

architect-cert

前言

回忆当年在学校的生活,真是幸福,毫无生活压力;时不常逃逃课,学习自己追求的技术,享受编程乐趣。那些年考过了不少有价值的认证,都不知道自己是怎么坚持下来的,5年时间一共完成了10的认证。

回过头来,我自己都不知道当时哪里来的动力,几乎是一件不可能完成的事情。一头走来跌跌撞撞,但最终找到了自己的职业方向。

目录

  1. SCJP
  2. SCWCD
  3. XML-141
  4. Websphere-285 & websphere-286
  5. DB2-700 & DB2-701
  6. SCBCD
  7. SCDJWS
  8. SCMAD

1. SCJP

我记得学Java是从大二开始的,对于专业课完全没有兴趣,同时又觉得C的代码很丑,觉得JSP做网页很牛的样子,就开始了我的Java生涯。自己学了半年,看着书按照例子,可以写一个小程序,但总觉得摸不着门,于是假期回到北京报了一个新东方的SCJP培训班,3天课程,800元。老师很负责把Java基础整个讲了一篇,我听的特别过瘾,(当时真应该留下老师的电话,特别感谢!)。

上完课后,剩下的25天的假期,我完全就在家中对着电脑度过的。从那一刻起,我终于开始对Java入门了。在假期的倒数第二天,我去考了SCJP1.4的考试。2个半小时考试,紧张的不得了,第一次用电脑考试,全英文的试题,硬着头皮一点一点读。题目都是选择题,单选和不定项选择题,对于不定项选择题ABCDEFGH 8个选择项给你,猜对的可能性很小,不过能让参加考试的有思路上的方向。考试过程中有摄像头一直监控,考试的屋子很小,一排5个台式机,每个人有一个小格子,一张草稿纸,外面是嘈杂的市场叫卖声音,坐满了2个半小时,检查了3篇,我最后是82分考过的。

从那时起,我终于开始对自己有信心了,并坚信自己找到自己的方向。

2. SCWCD

考完SCJP,对Java的基础核心有所了解了,但还是不知道Java能干什么。想做Web开发,又要学JSP和Servlet,当时甚至都不知道,JSP与ASP,PHP的区别。按照SCWCD的考试大纲,自己准备复习。虽然,还有补习班可以去学,但动辄4000-5000元的价格,已经不是一个学生可以承担了。

通过Google,在互联网上找到一切可以学习的教程,几乎看了几百份的教程,去相关的论坛天天逛逛。10年前我逛学习网站coderanch,竟然还在: http://www.coderanch.com/forums

当时看着网站上,老外各种晒着自己的认证,真是羡慕嫉妒恨啊!我就憋着,什么时候,我也能晒出我的认证,让别人也羡慕嫉妒一下。嘿嘿。

一咬牙一跺脚用了一个学期,就在屋里把所有的SCWCD认证的相关知识都学透了。这里不得不提一句,当时我认为写的最好的参考书:“SCWCD 认证专家应考指南”。

8821265-1_w

我吃透里面每一句话,完成所有的代码实例。就这样,我在第二个假期回到北京,又考过了SCWCD的认证。

此时,开发一个网站,对于我来说已经很简单了。不仅可以做网站,还可以利用Web容器的机制,实现各种复杂的功能,比如认证和授权,定时器,JNDI等。

3. XML-141

连续考了2个SUN的认证,几乎让我破产了,都是1200元一次大本投入,好在都通过了,不然真的要哭死了。

大三的时候,学校成立了IBM俱乐部,我就报名参加了,加入俱乐部的好处是考IBM的认证从原价1000元一次,变成学生价150元一次。简单一算,考一次SUN的认证可以考8次IBM的认证,接下我的重点马上转向IBM认证。我当时应该所有人中是最大的受益者了。

XML-141,这个认证是对我计算机软件基础知识形成最大支持的一个认证,让我认识到了计算机可以变成世界,也是我所有考过的认证中最难的一个。

这个认证的难点,主要在于知识面非常广,并与现实应用结合,所以对于当时我来说特别的困难。我将近花了1个月时间,从互联网上找到所有关于XML的资料,并每天晚上偷偷跑去旁听计算机研究生的XML课程,长期泡图书馆每天都盯着一本书 XML高级编程(第2版),这是一本看上去就不可能读完的书,16开1051页。伴着有点发霉的味道,第一遍读就花了3个月。对照着上面的例子,运行了所有程序。

507302-1_w

在这个学期结束的时候,我报名了参考XML-141的考试,虽然我认为我已准备的足够充分了,但是我还是高估了自己的基础知识,好像是48分没有通过。这个打击对于我来说是巨大的,我花了一学期的时间,几乎每天是每天12小时在学习,半年的努力竟然不能给自己划一个逗号。可能当时真的是自己没有企业应用的经验,很多案例题的解决方案都出了差错。痛定思痛,从图书馆借走了,“XML高级编程(第2版)” 背着回家了继续苦读。艰苦的又过了一个假期,我把 “XML高级编程(第2版)” 这本书一共看了3遍,而且把里面很多简单介绍的框架和程序包,都去对应的官网下载并运行。这1个月的补习,让我更加了解 为什么需要XML?XML能做什么?XML可以对原来方案有什么改进?JavaEE的Web容器中的以web.xml做为配置文件的意义!

再次开学的时候,我是带来卷土重来的决心回来的。开学的第三周,我又一次去考了XML-141这个认证,并且是90分的成绩通过了。这次考试的通过,我可能就已经具备了架构师的思考方式,并且很深刻地影响了我很多年的程序设计理念。

4. Websphere-285 & websphere-286

同是这个学期,我又完成参加了 Websphere-285和websphere-286的考试。对我来说,这两个考试基本上已经难度不大了,我是在一个下午,连续考了两门了,就像高考连考一样。最后很幸运的都通过了,并且没有给自己太大的压力。

Websphere-285,主要是考Websphere的家族产品,安装和使用。而Websphere-286,有点像SCJP和XML的结合,主要考如何用Websphere家族产品,设计基于JAVA的企业级解决方案。Websphere-286的证书,又依赖于SCJP的认证,考过了以后,Websphere-285很快就寄到了,Websphere-286还需要我先把SCJP的证书传真发给美国的IBM考试中心(就两张纸花了好几十块),这样就获得了这两个证书。

5. DB2-700 & DB2-701

DB2的认证,完全是无意所获得的。大三下学期,IBM的俱乐部开始推广IBM的数据库产品DB2,我也申请到了学生用的正版软件,然后就在自己的电脑上开始了各种倒腾。之前的专业课,学过MS-SQL-Server,对数据库有所了解。不过对于DB2来说,原来的基础知识是远远不够的。在DB2创建数据库,竟然要10行左右的命令,而不是像MS-SQL-Server点一个按钮就完成了的。

建库,建缓冲区,建表空间,定义分区大小,分离表空间和索引空间,再建Schema,建用户,分配权限,完成上面的整个过程,才能开始创建表,然后建视图,定义触发器和存储过程,性能监控,SQL执行计划,再通过JDBC与Java连接。。。一大串东西走下来,内容是丰富的,过程是复杂的,还需要细心整理各种命令脚本。不过对我来说,DB2已经没有特别难度了,只要一步一步仔细地操作一下来,就可以完成了。

DB2-700如同Websphere-285一样,主要是考DB2的家族产品,产品线,安装和使用。而DB2-701就考到了,从建库到存储过程,再到SQL优化,和最后的数据库案例设计。

一个学期又完成了2个认证,到大三结束的时候,我已经有了7个认证。

6. SCDJWS

这些认证意味什么?我开始的时候,很迷茫。当初的想法,是很天真很幼稚的,以为有了认证就可以去找到一份不错的工作;以为有了认证就可以直接去做架构师。但当你去找工作的时候,亮出认证的那一刻,你会发现,招聘的考官仅仅是有点的好奇,拿着各种认证证书,简单扫一遍,然后就是放到旁边,就跟认证不存在一样,继续问着他们那些应届毕业生在课堂中应该学到的那些问题。

我坦率的讲,我不是学计算机的,并且当时的确不了解 教课书里的算法,不会用时间复杂度和空间复杂度去解决数据结构中树或图的问题,我也不懂C和C++。回想我学的Java的所有知识体系中,都没讲要特别地要用Java去实现这些算法,JDK中的各种基础包已经封装好了这些算法。虽然当时各不理解,也几乎没有获得大公司的offer,不过我还是相信自己选的路,因为我知道我能做什么出来。

毕业了,回到北京。通过社会招聘,投简历,很容易的就找到了一份工作。几乎是回到北京的第二天投的简历,第三天就去面试,第四天就上班了。看着别人应聘的辛苦,我的这种上班速度还是有点小快呢。

从之前的面试经历,考认证已经不再是为了找工作了。我遇到的99%考官都不知道,认证是个啥玩意,有个别人的会说,我们这里招过获得SCJP认证的人也挺一般的。所以,我觉得中国和美国在教育上的差距真的是不可逾越的鸿沟。

看到coderanch上那些晒认证的美国人,无一不是通过认证获得了与自己付出相对应的工作,而在中国知识确是无法量化的。在我大三的时候,有个印度的朋友,获得SCJP后,向我请教如何学习Websphere, DB2, SCWCD,并想继续考认证,而且目标很明确的告诉我,有了认证就可以申请去美国的读书了。再一次的心理落差,让我感觉到中国教育的落后,中国人比印度人的出路都少。

从这以后,我考认证就不以找工作为目的了,而变成了为了丰富自己的知识结构而参加的考试,从而给自己的阶段性学习划上句号。

在XML成为标准以后,WebService和SOA成为后来的大火大紫的技术热点。为了明白底层的原理,我又开始准备SCDJWS的认证考试。很庆幸的是,有了XML的基础,在学习WebService的基础的架构的时候,没让我走太多的弯路,像DOM,SAX, SOAP, WSDL, UDDI, JAXB, JAXP, XSTL, XPath, XPointor等的各种技术规范,我都快速熟练地掌握了,对于SOA的框架层次理解地更清晰。虽然工作中难以用到这些,但很多时候别人的问题我已经能通过原理做解释了。我自己已经开始构思自己未来的系统了。

就算基础很好,学习SCDJWS也花了我半年的时间,白天上班晚上学习,拿到这个认证也是不容易的。

7. SCBCD

说起EJB,曾经是Java程序员都希望追求的技术,不是因为EJB有多牛,而EJB足够复杂。在Spring出现之前,Java社区的开发都是来自于SUN, IBM, Oracle的声音,他们在尝试用Java构建整个的软件生态系统,其中EJB就是SUN的企业级应用开发规范中必须的作为核心的一部分,分为Session Bean, Entity Bean, Message Bean。当然这个方案的实体Bean部分的设计比较复杂,比今天的Hibernate的复杂度要高好几个量级。BEA公司基于EJB做的宠物商店的demo,动辄就是上万行代码,让Java程序员感觉这才“高大上”的程序开发。

9037541-1_w

后来Spring框架出现了,expert one-on-one J2EE Development without EJB 一书动摇了大型软件厂商对企业级应用的定义。越来越多的复杂应用,开始像Spring的IOC模式迁移,Java开始变得更轻更自由了,Apache中的很多项目也开始基于Spring去重新构建,或者提供或Spring集成的接口了。后来,我们常用的SSH (Struts+Spring+Hibernate) 变形成了Java的Web开始的MVC铁三角组合。

当Hibernate在持久化层获得市场上的巨大成功以后,SUN开始重新定义EJB的规定,设计EJB3.0来轻量化EJB2.x,减少开发人员的准入门槛。

此时我依然是SUN的忠实粉丝,期待着EJB3.0的改进,我又完成了SCBCD的认证考试。而讽刺的是,完成考试后,我决定了放弃所有的ORM映射的框架,用iBatis的提供的原生SQL来实现持久层调用,同时自己写了一套基于MyBatis(iBatis)的持久层工具,更快速和轻量的构建我自己的Java系统。

8. SCMAD

SCMAD 这个认证是针对 JavaME手机移动的应用开发,考这个认证就有点奇葩了。当时,只是为了丰富自己的知识,虽然做半年过手机游戏,但没有理解很深,以后也不知道有没有机会再做手机相关的应用,为了完善自己的知识结构,从而考的SCMAD。

这个认证考试的时候,已经是我工作的第三年了,我已经没有太多的时间学习了,而且会很容易被身边的其他的事情所影响。复习过程中,虽然整体内容不太多,而且自己也有了一定的实际经验,但是拖的时间很长,花了将近一年的时间复习和准备。最后,也是考试券快过期之前完成的。

从2003年底大二开始到2008年初,5年时间我一共完成了10的认证。回过头来,我自己都不知道,当时哪里来的学习动力,几乎是一件不可能完成的事情。如果没有这些认证所学的基础知识,我现在又何去何从?

一篇博客,记录自己以前的学习经历。告诫后人珍惜时间,未来的成就,都是之前的积累,爆发就在未来的某个瞬间。

转载请注明出处:
http://blog.fens.me/architect-certification/

打赏作者

用WebStorm编辑Markdown

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/webstorm-markdown/

webstorm-markdown-title

前言

WebStorm是一个非常高效的开发工具,特别对于Web前端的开发。Markdown流行,因为其简化了HTML的语法,去掉了表单等复杂标签,以极简的语法只做网页展现。在WebStorem中编辑Markdown文档,是一种普遍的应用需求。

目录

  1. Markdown介绍
  2. 在WebStorem中安装Markdown插件
  3. 解决Markdown插件配置的问题

1. Markdown介绍

Markdown 是一种轻量级标记语言,创始人为约翰·格鲁伯(John Gruber)和亚伦·斯沃茨(Aaron Swartz)。它允许人们“使用易读易写的纯文本格式编写文档,然后转换成有效的XHTML(或者HTML)文档”。

Markdown的语法,对于没有编程经验的人,2-3个小时也可以掌握。各种语言基于的Markdown实现,都已经有了商业应用。

  • 高效,简约的设计,会让Markdown越走越远
  • 开源,免费的Liences,最后有可能会夺取微软Word软件的市场

本文不讲Markdown的语法,请大家自行查询。

Markdown的官方网站:http://daringfireball.net/projects/markdown/

2. 在WebStorem中安装Markdown插件

本来在WebStorem中安装Markdown插件很简单的事情,不知道是Idea的版本原因,还是Markdown插件设计者的原因,造成了一些使用问题,需要手动调整一些参数才正确使用。

我在这里也花了一些时间,找到了问题所在,因此写篇文章总结一下。

  • WebStorm版本:6.0.1
  • Makrdown插件版本:0.9.3

插件安装:

自动安装的截图:

webstorm-install

重起Webstorm软件,新建一个test.md文件。


APE: 测试Markdown语法
========================

Markdown语法

## INSTALL

#### 公共库安装
```{bash}
npm install
bower install
```

#### 私有库安装
```{bash}

```

## API

## demo

## License

private

我们看到,编辑器没有针对 markdown的文件进行适配,显示效果与文本文件无异。

markdown-txt

这就是问题所在!!

3. 解决Markdown插件配置的问题

经过排查发现,问题在于markdown插件没有和.md后缀的文件进行绑定!

查看文件类型的绑定:File –> Settings –> File Types –> Markdown files

markdown-files-old

增加*.md类型的绑定

markdown-files-add

然后,点击apply。

完成后,我们再打开之前编辑的test.md文件,Markdown的效果已经可以展示了。

markdown-show

底部标签text,preview可以在编辑和预览过程中切换效果,而且text也有语法高亮了。

如果想用Webstorm开发AngularJS,请参考文章:AngularJS最理想开发工具WebStorm

转载请注明出处:
http://blog.fens.me/webstorm-markdown/

打赏作者

Proftpd快速搭建FTP服务器

Ubuntu实用工具系列文章,将介绍基于Linux ubuntu的各种工具软件的配置和使用。有些工具大家早已耳熟能详,有些工具经常用到但确依然陌生。我将记录我在使用操作系统时,安装及配置工具上面的一些方法,把使用心得记录下来也便于自己的以后查找和回忆。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/linux-ftp-proftpd/

ftp-proftpd

前言

在Linux系统中,FTP服务器软件有很多,都已经成熟,像vsftpd, wu-ftp, Pure-FTPd等。但这些软件安装配置起来都比较麻烦,搭建个人的FTP服务器,还是Proftpd比较简单。

目录

  1. Proftpd介绍
  2. Proftpd安装
  3. Proftpd配置文件
  4. Proftpd使用场景
  5. 客户端访问

1. Proftpd介绍

Proftpd是一款开放源码的FTP服务器软件,它是原来世界范围使用最广泛的wu-ftpd的改进版,它修正了wu-ftpd的许多缺陷,在许多方面进行了重大的改进,其中一个重要变化就是它学习了Apache 的配置方式,使proftpd的配置和管理更加简单易懂。

有两种运行方式,独立服务器与超级服务器的子服务器。无论从安全性和稳定性,还是可配置性来说都是非常好的选择。

官方网站:http://www.proftpd.org/

2. Proftpd安装

系统环境

  • Linux Ubuntu 12.04.2 LTS 64bit server

安装Proftpd


~ sudo apt-get install proftpd

<hproftpd-install

选择“standalone”

查看proftpd状态


~ sudo /etc/init.d/proftpd status
ProFTPD is started in standalone mode, currently running.

~ ps -aux|grep ftp
proftpd   6674  0.0  0.1  94648  2092 ?        Ss   16:05   0:00 proftpd: (accepting connections)

#启动端口21
~ netstat -nltp|grep 21
tcp6       0      0 :::21                   :::*                    LISTEN      -

3. Proftpd配置文件

配置文件:/etc/proftpd/proftpd.conf


#配置服务器名
ServerName			""blog.fens.me FTP Server" 

#设置服务器运行模式,独立服务,或者被监管
ServerType			standalone 

#设置为默认服务器
DefaultServer			on 

#设置服务器进程运行使用的用户
User				proftpd

#设置服务器进程运行使用的组
Group			        nogroup

#设置关闭IPv6支持
UseIPv6			        off

#设置服务器接受请求的端口
Port				21 

#设置被动模式使用的端口范围
PassivePorts 			60000 65535

#设置用户上传文件的权限掩码
Umask				022

#设置用户被chroot锁定到的各自的Home目录
DefaultRoot			/ftp

#关闭欢迎信息显示
DeferWelcome			off 

#如果显示欢迎信息,则指定显示的文件
DisplayLogin			welcome.msg 

#指定切换文件夹时,显示的欢迎信息
DisplayChdir			.message 

#设置日志
SystemLog                       /var/log/proftp.log
TransferLog                     /var/log/proftp-transfer.log

#限定操作


<Limit SITE_CHMOD>
DenyAll
</Limit>

#设置匿名用户资源


<Anonymous "/ftp/c">
...
</Anonymous>

#配置存储目录权限


<Directory "/ftp/a/" >
<Limit ALL>
AllowUser x
AllowUser a1
DenyAll
</Limit>

<Limit CWD READ RETR DIRS>
AllowAll
</Limit>
</Directory>

Limit权限说明:

  • CWD : Change Working Directory 进入该目录
  • MKD : Make Directory 创建目录
  • RNFR : Rename from 更名
  • DELE : Delete 删除文件
  • RMD : Remove Directory 删除目录
  • READ : 可读
  • WRITE: 可写
  • STOR : 可上传
  • RETR : 可下载
  • DIRS : 允许列出目录
  • LOGIN: 允许登录
  • ALL : 全部

4. Proftpd使用场景

场景描述:某公司建立统一的FTP服务器(/ftp),公司有a部门(/ftp/a),b两个部门(/ftp/b),有独立的存储空间。

a1为a部门经理有对(/ftp/a)操作权限,a2为a部门员工只能读文件。

b1为b部门经理有对(/ftp/b)操作权限,b2为b部门员工只能读文件。

x为公司总经理,有对(/ftp)操作权限。

操作权限:


/ftp    -- x所有操作
/ftp/a  -- a1所有操作, a2只读
/ftp/b  -- b1所有操作, b2只读

命令操作:


# 创建FTP目录
sudo mkdir /ftp
sudo mkdir /ftp/a
sudo mkdir /ftp/b

# 创建用户组
sudo groupadd a
sudo groupadd b

Ubuntu系统配置nologin,与其他Linux稍有不同


~  sudo vi /etc/shells

# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/tmux
/usr/bin/screen
/usr/sbin/nologin

最后一行增加/usr/sbin/nologin

创建用户并设置nologin, 禁止FTP账户登陆


sudo useradd a1 -g a -s /usr/sbin/nologin
sudo useradd a2 -g a -s /usr/sbin/nologin
sudo useradd b1 -g b -s /usr/sbin/nologin
sudo useradd b2 -g b -s /usr/sbin/nologin
sudo useradd x -G a,b -s /usr/sbin/nologin

#设置账户密码
echo -e "a1:123" | sudo chpasswd
echo -e "a2:123" | sudo chpasswd
echo -e "b1:123" | sudo chpasswd
echo -e "b1:123" | sudo chpasswd
echo -e "x:123" | sudo chpasswd

#设置目录权限
sudo chown x /ftp
sudo chown a1:a /ftp/a
sudo chmod 770 /ftp/a
sudo chmod g+s /ftp/a
sudo chown b1:b /ftp/b
sudo chmod 770 /ftp/b
sudo chmod g+s /ftp/b

修改配置文件:/etc/proftpd/proftpd.conf


~ sudo vi /etc/proftpd/proftpd.conf

ServerName "blog.fens.me FTP Server"
ServerType standalone
DefaultServer on
Port 21
Umask 022
MaxInstances 30
User proftpd
Group nogroup
DefaultRoot /ftp
AllowOverwrite on

SystemLog /var/log/proftp.log
TransferLog /var/log/proftp-transfer.log

<Directory "/ftp/*">
<Limit CWD READ>
AllowAll
</Limit>
</Directory>

<Directory "/ftp/a/" >
<Limit ALL>
AllowUser x
AllowUser a1
DenyAll
</Limit>

<Limit CWD READ RETR DIRS>
AllowAll
</Limit>
</Directory>

<Directory "/ftp/b/" >
<Limit ALL>
AllowUser x
AllowUser b1
DenyAll
</Limit>

<Limit CWD READ RETR DIRS>
AllowAll
</Limit>
</Directory>

<Limit SITE_CHMOD>
DenyAll
</Limit>

重新服务器


~ sudo /etc/init.d/proftpd restart
 * Stopping ftp server proftpd        [ OK ]
 * Starting ftp server proftpd 

5. 客户端访问

客户端命令行:Win7 64bit Command

模拟a1用户登陆:


~ ftp

#建立连接
ftp> open 192.168.1.201
连接到 192.168.1.201。
220 ProFTPD 1.3.4a Server (blog.fens.me FTP Server) [::ffff:192.168.1.201]
用户(192.168.1.201:(none)): a1
331 Password required for a1
密码:
230 User a1 logged in

#查看目录 
ftp> dir
200 PORT command successful
150 Opening ASCII mode data connection for file list
drwxrws---   2 a1       a            4096 Nov  3 12:59 a
drwxrws---   2 b1       b            4096 Nov  3 12:25 b
226 Transfer complete
ftp: 收到 116 字节,用时 0.00秒 58.00千字节/秒。

ftp> cd a
250 CWD command successful

ftp> pwd
257 "/a" is the current directory

ftp> dir
200 PORT command successful
150 Opening ASCII mode data connection for file list
-rw-r--r--   1 a2       a           55723 Nov  3 12:56 36kryunjiasu.docx
-rw-r--r--   1 a1       a               4 Nov  3 12:24 test.txt
226 Transfer complete
ftp: 收到 139 字节,用时 0.00秒 69.50千字节/秒。

#上传文件
ftp> put c:\22.log
200 PORT command successful
150 Opening ASCII mode data connection for 22.log
226 Transfer complete
ftp: 发送 120 字节,用时 0.06秒 2.18千字节/秒。

#下载文件
ftp> get test.txt
200 PORT command successful
150 Opening ASCII mode data connection for test.txt (4 bytes)
226 Transfer complete
ftp: 收到 5 字节,用时 0.00秒 5000.00千字节/秒。

#尝试访问B目录,出错
ftp> cd ../b
550 ../b: No such file or directory

#退出
ftp> bye
221 Goodbye.

模拟a2用户登陆:


~ ftp

#建立连接
ftp> open 192.168.1.201
连接到 192.168.1.201。
220 ProFTPD 1.3.4a Server (blog.fens.me FTP Server) [::ffff:192.168.1.201]
用户(192.168.1.201:(none)): a2
331 Password required for a2
密码:
230 User a2 logged in

#查看目录 
ftp> dir
200 PORT command successful
150 Opening ASCII mode data connection for file list
drwxrws---   2 a1       a            4096 Nov  3 13:09 a
drwxrws---   2 b1       b            4096 Nov  3 12:25 b
226 Transfer complete
ftp: 收到 116 字节,用时 0.00秒 116.00千字节/秒。

#上传文件,出错
ftp> put c:\11.log
200 PORT command successful
550 11.log: Operation not permitted

#下载文件
ftp> get 22.log
200 PORT command successful
150 Opening ASCII mode data connection for 22.log (114 bytes)
226 Transfer complete
ftp: 收到 120 字节,用时 0.00秒 120000.00千字节/秒。

用Proftpd我们快速建立了一个公司内部的FTP服务器,比wu-ftpd要方便。

转载请注明出处:
http://blog.fens.me/linux-ftp-proftpd/

打赏作者