Ubuntu下启动/重启/停止apache服务器
Task: Start Apache 2 Server /启动apache服务
# /etc/init.d/apache2 start
or
$ sudo /etc/init.d/apache2 start
Task: Restart Apache 2 Server /重启apache服务
# /etc/init.d/apache2 restart
or
$ sudo /etc/init.d/apache2 restart
Task: Stop Apache 2 Server /停止apache服务
# /etc/init.d/apache2 stop
or
$ sudo /etc/init.d/apache2 stop
关于ubuntu下的httpd.conf
ubuntu下的httpd.conf位置在 /etc/apache2/ 初始还是空的
其实,apache2的配置文件在 /etc/apache2/apache2.conf
apache2 根据配置功能的不同, 对配置文件进行了分割, 这样更利于管理
同时,也不会随着httpd.conf的增加而变化。
另外,我们备份网站的一些配置文件也很方便,可以在 sites-enabled配置
WordPress自动升级插件时需要填写FTP信息的解决
sudo chown -R www-data.www-data /home/username/wordpress
OpenVPN HOWTO 中文版
OpenVPN HOWTO
介绍
此文档描述一个典型的Home到Office的通信中OpenVPN的配置。这份HOWTO举了一个完整的配置实例,在man page手册页中有一个更为简单的例子。
此HOWTO文档还有如下格式:
PDF
PostScript
附加的文档
其他的一些很好的文档及HOWTO 为不同环境下配置OpenVPN而作。
基本的隧道(Tunnel)类型
OpenVPN可以创建两种基本的隧道类型:
Routed IP tunnels – 适用于不需广播的点对点IP(point-to-point)通信。比起桥接网络隧道来略显得更有效率些而且更易配置。此HOWTO文档涵盖了Routed IP tunnels。
Bridged Ethernet Tunnels(桥接网络隧道) – 能用于IP协议或非IP协议的隧道。这种类型的隧道更适合于使用广播(broadcast)的应用,比如某些Windows网络游戏。配置起来稍微复杂些。关于桥接网络隧道的Mini-HOWTO。
Routed IP tunnel HOWTO
我们会尝试描述一个完整的系统配置,期间涉及到防火墙,VPN,NAT以及他们彼此间的相互关联,我们不会孤立的一部分一部分的探讨VPN设置。
在我们的例子中,Home和Office机器所在的私有网络都分别通过了一台具有公网IP地址的网关机器接入互联网。每台网关机器都配有两块网卡(NIC),一块联入内网,另一块联入公网。网关机器为内网机器提供NAT,防火墙,VPN服务。Home及Office机器的配置基本一样,除了Office的网关机器为固定IP,Home机器的IP为DHCP动态获取。
在以下例子中所显示的配置文件在OpenVPN发布版本中是有效的。
Home和Office的IP网络参数
Home Office
本地子网 (内网地址) 10.0.1.0/24 10.0.0.0/24
Tunnel Endpoint (内网地址) 10.1.0.2 10.1.0.1
OpenVPN Gateway (公网地址) DHCP client, need not be explicitly specified 1.2.3.4
安装 OpenVPN
如果你的系统没有OpenSSL库,你需要 下载和安装它。
如果你想使用VPN连接的压缩特性,或者你想将OpenVPN安装为一个RPM包,安装LZO Library。
如果你使用Linux 2.2 或更早版本,下载 TUN/TAP driver。对于Linux 2.4.7及以上版本的用户TUN/TAP 驱动已经捆绑到内核中。Linux 2.4.0 -> 2.4.6 的用户需要留意INSTALL文件末尾的注意信息。
现在下载 OpenVPN 的最新发布版:
http://prdownloads.sourceforge.net/openvpn/openvpn-1.6.0.tar.gz
使用 tarball 安装
解开发布版的压缩包:
gzip -dc openvpn-1.6.0.tar.gz | tar xvf -
创建 OpenVPN:
cd openvpn-1.6.0
./configure
make
make install
如果你未下载 LZO Library ,将 –disable-lzo 加入到 configure 命令中。也可以启用其他的选型,比如 pthread (./configure –enable-pthread) 用来提高 SSL/TLS 动态密钥交换的响应速度。命令
./configure –help
将显示所有的配置选型。
从 RPM 安装
首先创建RPM文件。此操作需要 OpenSSl,pthread,和LZO 库。通常只会有 LZO 库需要额外下载并安装;; 其他的库在大多数的Linux 发行版本中已经作为缺省安装。
rpmbuild -tb openvpn-1.6.0.tar.gz
RPM 创建过程会生成大量输出信息。创建成功后,在输出信息的末尾附记会有一个提示信息说明生成的二进制RPM文件名。用如下命令安装该文件:
rpm -Uvh binary-RPM-file
配置 TUN/TAP 驱动
仅需一次的配置
如果你使用 Linux 2.4.7 或更高版本,十分幸运 TUN/TAP 驱动已经捆绑到内核中。你可以通过如下命令确认:
locate if_tun.h
此命令产生类似这样的信息 /usr/include/linux/if_tun.h 。
对于 Linux 2.4.7 或更高版本,如果你通过 tarball 安装,输入如下命令配置 TUN/TAP 设备节点(如果你通过 RPM 安装可以忽略这一步,因为RPM为你自动创建该节点):
mknod /dev/net/tun c 10 200
如果你使用 Linux 2.2,你需要获得 版本 1.1 的TUN/TAP kernel module 并按照安装说明进行操作。
每次系统启动后需要执行一次的配置
在 Linux 上使用 OpenVPN 或任何用到 TUN/TAP 设备的程序前需要载入 TUN/TAP kernel module:
modprobe tun
并且启用 IP 转发:
echo 1 > /proc/sys/net/ipv4/ip_forward
配置 Firewall 和 NAT
这一小节假定你使用 Linux 2.4 和 iptables 防火墙。这里是一个防火墙配置的例子,它为内网机器访问互联网提供了NAT服务,stateful outgoing connection tracking, 和 OpenVPN 支持:
sample-config-files/firewall.sh
#!/bin/bash
OpenVPN-aware 防火墙例子.
eth0 连接到互联网.
eth1 连接到内部子网.
这里改变你的子网地址
Home 使用 10.0.1.0/24
Office 使用 10.0.0.0/24
PRIVATE=10.0.0.0/24
Loopback 地址
LOOP=127.0.0.1
删除旧的 iptables 规则
并且临时阻塞网络通信
iptables -P OUTPUT DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -F
设置缺省策略
iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP
iptables -P FORWARD DROP
阻止外部数据包使用 loopback 地址
iptables -A INPUT -i eth0 -s $LOOP -j DROP
iptables -A FORWARD -i eth0 -s $LOOP -j DROP
iptables -A INPUT -i eth0 -d $LOOP -j DROP
iptables -A FORWARD -i eth0 -d $LOOP -j DROP
任何从互联网流入的数据包都必须使用真实互联网地址
iptables -A FORWARD -i eth0 -s 192.168.0.0/16 -j DROP
iptables -A FORWARD -i eth0 -s 172.16.0.0/12 -j DROP
iptables -A FORWARD -i eth0 -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP
阻塞 NetBios 数据包流出(如果内网有 windows 机器)。
这不会影响 VPN 隧道上的NetBios通信,
但它会阻止本地 windows 机器向互联网广播自己。
iptables -A FORWARD -p tcp –sport 137:139 -o eth0 -j DROP
iptables -A FORWARD -p udp –sport 137:139 -o eth0 -j DROP
iptables -A OUTPUT -p tcp –sport 137:139 -o eth0 -j DROP
iptables -A OUTPUT -p udp –sport 137:139 -o eth0 -j DROP
检查流向互联网的数据包中源地址的合法性
iptables -A FORWARD -s ! $PRIVATE -i eth1 -j DROP
允许本地 loopback
iptables -A INPUT -s $LOOP -j ACCEPT
iptables -A INPUT -d $LOOP -j ACCEPT
允许向内的(incoming) ping 操作(可以禁止)
iptables -A INPUT -p icmp –icmp-type echo-request -j ACCEPT
允许 www 和 ssh 服务(可以禁止)
iptables -A INPUT -p tcp –dport http -j ACCEPT
iptables -A INPUT -p tcp –dport ssh -j ACCEPT
允许向内的(incoming) OpenVPN 数据包
对于每条 OpenVPN 隧道要将以下每行重复,
改变 –dport n 为 OpenVPN UDP 实际端口。
#
在 OpenVPN中,端口号由 –port n 选项控制。
如果你将这个选型写入配置文件,
你可以去掉 ‘–’后这一串字符。
#
If you taking the stateful firewall
approach (参看 OpenVPN HOWTO),
那么注释掉下面这一行。
iptables -A INPUT -p udp –dport 5000 -j ACCEPT
允许来自 TUN/TAP 设备的数据包。
当 OpenVPN 运行于安全模式时,
他会对 tun 或 tap 接口上的数据包到达前进行验证。
也就是说,这里添加的任何过滤不是必需的,
除非你想对有可能溢出隧道的数据包类型进行严格约束。
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -j ACCEPT
iptables -A INPUT -i tap+ -j ACCEPT
iptables -A FORWARD -i tap+ -j ACCEPT
允许来自内网的数据包
iptables -A INPUT -i eth1 -j ACCEPT
iptables -A FORWARD -i eth1 -j ACCEPT
保持来自本机和内网数据包的连接状态
iptables -A OUTPUT -m state –state NEW -o eth0 -j ACCEPT
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state –state NEW -o eth0 -j ACCEPT
iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT
伪装本地子网
iptables -t nat -A POSTROUTING -s $PRIVATE -o eth0 -j MASQUERADE
OpenVPN 在防火墙设置中提供少量的附加选项:
If both OpenVPN peers reference the other with an explicit –remote option, and stateful firewalls that provide UDP connection tracking (such as iptables) exist between the peers, it is possible to run OpenVPN without any explicit firewall rules, if both peers originate regular pings to each other to keep the connection alive. To do this, simply run OpenVPN with the –remote peer option, and specify –ping 15 to ensure that packets flow over the tunnel at least once every 15 seconds.
上面的选项在隧道一端(peer)频繁变更 IP 地址比如说DHCP或拨号时,显得不够方便。在这种情况下,以上简单的防火墙配置将允许任何IP地址通过UDP端口5000(OpenVPN 的缺省UDP端口) 流入数据包。在 OpenVPN 的安全模式下,所有流入隧道的数据或者通过安全验证或者被丢弃,所以它通常被认为是安全的。
如果你选择完全开放 OpenVPN 的 incoming UDP 端口就像上面简单防火墙中的配置一样,你可能会想利用 –tls-auth 选项在 TLS 控制通道上作双倍的验证,同时使用 RSA 密钥和预先分享的密码短语(passphrase)来作为防御 DoS 或 active 攻击的第二道防线。关于–tls-auth 的更多信息,参考 openvpn man page。
创建 RSA 证书和密钥
OpenVPN 有两种安全模式,一种基于使用 RSA 证书和密钥的 SSL/TLS,一种使用预先分享的静态密钥。SSL/TLS + RSA 密钥被证明是一种最安全的选择,静态密钥优势则在于简洁。如果你想使用 RSA 密钥,继续往下读。要使用静态密钥,向前跳到 创建预分享静态密钥 一节.
我们将使用 openssl 命令创建 RSA 证书和密钥,该命令包含在 OpenSSL 库的发布程序中。
RSA 证书是一种公开密钥,在其中还含有其他安全域,比如说证书持有者的 Common Name 或 email 地址。OpenVPN 有能力在进行认证前对这些域进行测试。更多信息参考 openvpn man page 中的 –tls-verify 选项。
在我们的例子中遵从 apache 惯例使用 .crt 扩展名表示证书文件,.key 扩展名表示私钥。私钥文件必须安全保管。证书文件可以自由发布共享。
选择一台机器比如 Office 作为密钥管理主机。
首先编辑文件 /usr/share/ssl/openssl.cnf (这个文件也许在其他地方,可以用 locate openssl.cnf 命令找到它)。
你或许会对它作一些修改:
建立一个目录作为密钥的工作目录,将 dir 指向它。
考虑增加有限期限 default_days 以免你的 VPN 在工作整一年后莫名其妙的终止。
设定 certificate 和 private_key 指向你的根证书 (master certificate authority certificate)和私钥文件(我们马上要生成它)。在下面的例子中,我们假定你的证书文件名为 my-ca.crt,你的私钥文件名为 my-ca.key 。
注意文件 index.txt 和 serial。将 index.txt 清空,serial 初始化为包含一个数字序列比如 01.
如果你狂热的追求密钥长度,那可以将 default_bits 增加到2048。 对于打开 pthread 支持(可以后台处理 RSA 密钥)的 OpenVPN 处理2048位的 RSA 密钥是毫无问题的。甚至没有打开 pthread 支持时也可以使用更长的密钥,但你会在隧道中作 SSL/TLS 密钥协商时感觉到响应时间的延迟。这里有一份选择 RSA 密钥长度的很好的文章,参见 April 2002 issue of Bruce Schneier’s Crypto-Gram Newsletter.
openssl.cnf 编辑完后,创建根证书/私钥对(master certificate authority certificate/private-key pair):
openssl req -nodes -new -x509 -keyout my-ca.key -out my-ca.crt -days 3650
这将会创建一对有效期为十年的根证书/私钥对。
现在为 Home 和 Office 创建 证书/私钥对:
openssl req -nodes -new -keyout office.key -out office.csr
openssl ca -out office.crt -in office.csr
openssl req -nodes -new -keyout home.key -out home.csr
openssl ca -out home.crt -in home.csr
现在将 home.crt, home.key, 和 my-ca.crt 文件通过安全途径拷贝到 Home 机器上,尽管实际上只有.key 才被认为是应该保密的。
现在在 Office 机器上创建 Diffie Hellman 参数,使用下列命令:
openssl dhparam -out dh1024.pem 1024
如果在 openssl.cnf 中增大了密钥位数,相应的这里也要把 1024 改为 2048。
对于偏执狂可以考虑去掉上面 openssl 命令中的-nodes 选项。其结果是对每一个私钥进行口令加密,从而保证当有人攻入你的主机盗走你的私钥时仍有一定的安全性。麻烦的是每次当你使用 OpenVPN 时都需要输入口令。更多信息参考 openvpn man page 中的 –askpass 选项。
如果你对手工管理 RSA 密钥觉得困惑,那要指出一点 OpenVPN 可以很好的同任何 X509 证书管理工具或服务包括商业化的 CAs 如 Thawte or Verisign等协同工作。检索 OpenCA 项目可以查看有哪些同证书/密钥管理工具 配合良好的开源项目。
另外,OpenVPN 发布版中包含了一组脚本能够简化 RSA 证书和密钥管理。
在 OpenVPN 上使用商业证书(CAs)的重要提示
It should be noted that OpenVPN’s security model in SSL/TLS mode is oriented toward users who will generate their own root certificate, and hence be their own CA. In SSL/TLS mode, OpenVPN authenticates its peer by checking that the peer-supplied certificate was signed by the CA certificate specified in the –ca option. Like the SSL-based secure web, the security of OpenVPN’s SSL/TLS mode rests on the infeasibility of forging a root certificate signature.
This authentication procedure works perfectly well if you have generated your own root certificate, but presents a problem if you wish to use the root certificate of a commercial CA such as Thawte. If, for example, you specified Thawte’s root certificate in the –ca option, any certificate signed by Thawte would now be able to authenticate with your OpenVPN peer – certainly not what you would want.
Luckily there is a solution to this problem in the –tls-verify option. This option will allow you to execute a command to check the contents of a certificate, to fine-tune the selection of which certificate is allowed, and which is not. See the script verify-cn in the sample-scripts subdirectory for an example of how to do this, and also see the man page for the –tls-verify option.
使用 SSL/TLS 模式和 RSA 证书/密钥的配置文件
在我们的例子中,我们使用 OpenVPN 配置文件。OpenVPN 允许由命令行或一个或多个配置文件指定参数。在命令行中由”–”引导的参数在配置文件中是可以忽略”–”的,命令行中则不行。
设置下列配置文件:
sample-config-files/tls-office.conf
#
Sample OpenVPN configuration file for
office using SSL/TLS mode and RSA certificates/keys.
#
‘#’ 或 ‘;’ 用于表明注释.
使用 dynamic tun device.
For Linux 2.2 or non-Linux OSes,
你可以使用显式指明的设备号,比如”tun1”
OpenVPN 也支持虚拟网络 “tap” devices;
dev tun
10.1.0.1 is our local VPN endpoint (office).
10.1.0.2 is our remote VPN endpoint (home).
ifconfig 10.1.0.1 10.1.0.2
up 脚本将在 VPN 激活时建立路由
up ./office.up
在 SSL/TLS 密钥交换时,Office 作为 server,Home 作为 client
tls-server
Diffie-Hellman Parameters (tls-server only)
dh dh1024.pem
Certificate Authority file
ca my-ca.crt
Our certificate/public key
cert office.crt
Our private key
key office.key
OpenVPN 缺省使用 UDP 端口 5000 .
每一个 OpenVPN tunnel 必须使用一个不同的端口.
lport 和 rport 被用于指明本地或远程的不同端口
; port 5000
出于安全考虑,初始化后UID 和GID 权限将降为 “nobody”
; user nobody
; group nobody
如果你的OpenVPN支持LZO 压缩,去掉这一行的注释
; comp-lzo
#
每15秒向远端主机发送一个 UDP ping
stateful firewall connection
alive. Uncomment this
out if you are using a stateful
firewall.
; ping 15
Uncomment this section for a more reliable detection when a system
loses its connection. For example, dial-ups or laptops that
travel to other locations.
; ping 15
; ping-restart 45
; ping-timer-rem
; persist-tun
; persist-key
信息细节等级
0 – 除非发生致命错误,否则保持安静。
1 – 非常安静,但会显示一些非致命网络错误。
3 – 中等输出,通常情况下的很好选择。
9 – 非常详细,用于诊断错误。
verb 3
sample-config-files/office.up
#!/bin/bash
route add -net 10.0.1.0 netmask 255.255.255.0 gw $5
sample-config-files/tls-home.conf
#
Sample OpenVPN configuration file for
home using SSL/TLS mode and RSA certificates/keys.
#
‘#’ or ‘;’ may be used to delimit comments.
Use a dynamic tun device.
For Linux 2.2 or non-Linux OSes,
you may want to use an explicit
unit number such as “tun1”.
OpenVPN also supports virtual
ethernet “tap” devices.
dev tun
Our OpenVPN peer is the office gateway.
remote 1.2.3.4
10.1.0.2 is our local VPN endpoint (home).
10.1.0.1 is our remote VPN endpoint (office).
ifconfig 10.1.0.2 10.1.0.1
Our up script will establish routes
once the VPN is alive.
up ./home.up
在 SSL/TLS 密钥交换时,Office 作为 server,Home 作为 client
tls-client
Certificate Authority file
ca my-ca.crt
Our certificate/public key
cert home.crt
Our private key
key home.key
OpenVPN 缺省使用 UDP 端口 5000 .
每一个 OpenVPN tunnel 必须使用一个不同的端口.
lport 和 rport 被用于指明本地或远程的不同端口
; port 5000
出于安全考虑,初始化后UID 和GID 权限将降为 “nobody”
; user nobody
; group nobody
如果你的OpenVPN支持LZO 压缩,去掉这一行的注释
; comp-lzo
每15秒向远端主机发送一个 UDP ping
stateful firewall connection
alive. Uncomment this
out if you are using a stateful
firewall.
; ping 15
Uncomment this section for a more reliable detection when a system
loses its connection. For example, dial-ups or laptops that
travel to other locations.
; ping 15
; ping-restart 45
; ping-timer-rem
; persist-tun
; persist-key
信息细节等级
0 – 除非发生致命错误,否则保持安静。
1 – 非常安静,但会显示一些非致命网络错误。
3 – 中等输出,通常情况下的很好选择。
9 – 非常详细,用于诊断错误。
verb 3
sample-config-files/home.up
#!/bin/bash
route add -net 10.0.0.0 netmask 255.255.255.0 gw $5
创建一个预分享静态密钥(Pre-Shared Static Key)
同 RSA 密钥管理极为不同的是,使用预分享静态密钥是十分简单。The major downside of using static keys is that you give up the notion of perfect forward secrecy, meaning that if an attacker steals your static key, everything that was ever encrypted with it is compromised.
使用如下命令生成静态密钥:
openvpn –genkey –secret static.key
静态密钥文件由ascii组成,就像下面这样:
—–BEGIN OpenVPN Static key V1—–
e5e4d6af39289d53
171ecc237a8f996a
97743d146661405e
c724d5913c550a0c
30a48e52dfbeceb6
e2e7bd4a8357df78
4609fe35bbe99c32
bdf974952ade8fb9
71c204aaf4f256ba
eeda7aed4822ff98
fd66da2efa9bf8c5
e70996353e0f96a9
c94c9f9afb17637b
283da25cc99b37bf
6f7e15b38aedc3e8
e6adb40fca5c5463
—–END OpenVPN Static key V1—–
一个 OpenVPN 静态密钥包含有足够的熵值,其中512位作为加密键,512位作为身份验证的 HMAC。(An OpenVPN static key file contains enough entropy to key both a 512 bit cipher key and a 512 bit HMAC key for authentication.)
通过安全的媒介将 static.key 拷贝到另一端(peer),比如使用scp 或 ssh 中的拷贝、粘贴。
使用预共享静态密钥(Pre-Shared Static Key)的配置文件
在我们的例子中,我们使用 OpenVPN 配置文件。OpenVPN 允许由命令行或一个或多个配置文件指定参数。在命令行中由”–”引导的参数在配置文件中是可以忽略”–”的,命令行中则不行。
Set up the following configuration files:
sample-config-files/static-office.conf
#
Sample OpenVPN configuration file for
office using a pre-shared static key.
#
‘#’ or ‘;’ may be used to delimit comments.
Use a dynamic tun device.
For Linux 2.2 or non-Linux OSes,
you may want to use an explicit
unit number such as “tun1”.
OpenVPN also supports virtual
ethernet “tap” devices.
dev tun
10.1.0.1 is our local VPN endpoint (office).
10.1.0.2 is our remote VPN endpoint (home).
ifconfig 10.1.0.1 10.1.0.2
Our up script will establish routes
once the VPN is alive.
up ./office.up
Our pre-shared static key
secret static.key
OpenVPN uses UDP port 5000 by default.
Each OpenVPN tunnel must use
a different port number.
lport or rport can be used
to denote different ports
for local and remote.
; port 5000
Downgrade UID and GID to
“nobody” after initialization
for extra security.
; user nobody
; group nobody
If you built OpenVPN with
LZO compression, uncomment
out the following line.
; comp-lzo
Send a UDP ping to remote once
every 15 seconds to keep
stateful firewall connection
alive. Uncomment this
out if you are using a stateful
firewall.
; ping 15
Uncomment this section for a more reliable detection when a system
loses its connection. For example, dial-ups or laptops that
travel to other locations.
; ping 15
; ping-restart 45
; ping-timer-rem
; persist-tun
; persist-key
信息细节等级
0 – 除非发生致命错误,否则保持安静。
1 – 非常安静,但会显示一些非致命网络错误。
3 – 中等输出,通常情况下的很好选择。
9 – 非常详细,用于诊断错误。
verb 3
sample-config-files/office.up
#!/bin/bash
route add -net 10.0.1.0 netmask 255.255.255.0 gw $5
sample-config-files/static-home.conf
#
Sample OpenVPN configuration file for
home using a pre-shared static key.
#
‘#’ or ‘;’ may be used to delimit comments.
Use a dynamic tun device.
For Linux 2.2 or non-Linux OSes,
you may want to use an explicit
unit number such as “tun1”.
OpenVPN also supports virtual
ethernet “tap” devices.
dev tun
Our OpenVPN peer is the office gateway.
remote 1.2.3.4
10.1.0.2 is our local VPN endpoint (home).
10.1.0.1 is our remote VPN endpoint (office).
ifconfig 10.1.0.2 10.1.0.1
Our up script will establish routes
once the VPN is alive.
up ./home.up
Our pre-shared static key
secret static.key
OpenVPN uses UDP port 5000 by default.
Each OpenVPN tunnel must use
a different port number.
lport or rport can be used
to denote different ports
for local and remote.
; port 5000
Downgrade UID and GID to
“nobody” after initialization
for extra security.
; user nobody
; group nobody
If you built OpenVPN with
LZO compression, uncomment
out the following line.
; comp-lzo
Send a UDP ping to remote once
every 15 seconds to keep
stateful firewall connection
alive. Uncomment this
out if you are using a stateful
firewall.
; ping 15
Uncomment this section for a more reliable detection when a system
loses its connection. For example, dial-ups or laptops that
travel to other locations.
; ping 15
; ping-restart 45
; ping-timer-rem
; persist-tun
; persist-key
信息细节等级
0 – 除非发生致命错误,否则保持安静。
1 – 非常安静,但会显示一些非致命网络错误。
3 – 中等输出,通常情况下的很好选择。
9 – 非常详细,用于诊断错误。
verb 3
sample-config-files/home.up
#!/bin/bash
route add -net 10.0.0.0 netmask 255.255.255.0 gw $5
在 SSL/TLS mode 下启动 VPN
Home 机器端,用如下命令启动 VPN :
openvpn –config tls-home.conf
Office 端,用如下命令启动 VPN :
openvpn –config tls-office.conf
在静态密钥模式(Static Key mode)下启动 VPN
Home 机器端,用如下命令启动 VPN :
openvpn –config static-home.conf
Office 端,用如下命令启动 VPN :
openvpn –config static-office.conf
测试 VPN
在 Home 机器上,可以通过 ping Office 主机(经过隧道)来测试 VPN:
ping 10.1.0.1
在 Office 机器上,可以通过 ping Home 主机(经过隧道)来测试 VPN:
ping 10.1.0.2
如果测试失败但无输出信息,可以编辑配置文件将 信息细节等级 调为8(将产生大量细节信息用于调试)。参考FAQ 获取更多错误处理信息。
如果测试通过,可以尝试经过隧道 ping 另一端子网中的机器(网关机器除外)来测试路由。基本上 10.0.1.0/24 子网中的任一机器可以访问 10.0.1.0/24 子网中的任意机器,反之亦然。
如果工作正常,恭喜你!如果不正常,你可以查看邮件列表 OpenVPN Mailing List 有没有相似问题。如果问题依旧,可以考虑贴到 openvpn-users 列表。
Make the VPN DHCP-aware
回想一下,在我们的网络配置中,Home是使用动态 IP,地址可以任意的变化。如果你的客户端(client daemon)使用 dhcpcd ,那写一个适应IP地址任意变化的脚本也是很容易的。这个脚本或许被命名为 /etc/dhcpc/dhcpcd-eth0.exe.
基本上你要作的就是将下面这一行加入脚本,其作用是向 OpenVPn daemon 发送一个SIGUSR1 或 SIGHUP 信号:
killall -HUP openvpn
当 OpenVPN 收到这个信号后会关闭连接随后再使用DHCP获取的新的IP重新与对端连接。
如果你连接的对端由于 DHCP 重置而改变IP地址,你也许会考虑使用 –float 选项。
DHCP 重置时也有可能是 SIGUSR1 起作用,相比SIGHUP 它会在OpenVPN子系统重置时提供更多的进程回收控制。–ping 和 –ping-restart 也会内在的产生SIGUSR1信号。
–persist-tun 选项实现重置时不需关闭重新打开 TUN 设备(这就为在DHCP上的隧道提供了一种无缝连接)。
–persist-remote-ip 选项实现在DHCP重置时会保留远端 IP 地址。这样就允许 OpenVPN 隧道的两端都可以为DHCP client。
–persist-key 选项实现在重启时不用重新读取密钥文件(这样就允许 OpenVPN daemon 在权限降为 –user 或 –group 时也能实现重启)。
在 动态IP 环境下使用 OpenVPN的 更多信息,可参考FAQ 。
OpenVPN 也能在如下环境使用:连接两端都为动态地址。
系统重启时自动启动 VPN
首先建立一个目录存放OpenVPN密钥和配置文件,如: /etc/openvpn.
选择使用TLS模式或静态密钥模式 ,将适当的 .conf, .up, .key, .pem, 和 .crt 文件拷入 目录/etc/openvpn.
保护你的 .key 文件:
chmod go-rwx /etc/openvpn/*.key
如果使用 Linux iptables,编辑防火墙配置文件 firewall.sh,将相应的变动拷入目录 /etc/openvpn.
创建类似如下的 startup 脚本:
sample-config-files/openvpn-startup.sh
#!/bin/bash
A sample OpenVPN startup script
for Linux.
openvpn config file directory
dir=/etc/openvpn
载入防火墙
$dir/firewall.sh
载入 TUN/TAP kernel module
modprobe tun
开启IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward
为每一个VPN隧道唤醒一个守护(daemon)模式的openvpn
Invoke openvpn for each VPN tunnel
in daemon mode. Alternatively,
you could remove “–daemon” from
the command line and add “daemon”
to the config file.
#
Each tunnel should run on a separate
UDP port. Use the “port” option
to control this. Like all of
OpenVPN’s options, you can
specify “–port 8000” on the command
line or “port 8000” in the config
file.
openvpn –cd $dir –daemon –config vpn1.conf
openvpn –cd $dir –daemon –config vpn2.conf
openvpn –cd $dir –daemon –config vpn2.conf
创建类似如下的 shutdown 脚本:
sample-config-files/openvpn-shutdown.sh
#!/bin/bash
stop all openvpn processes
killall -TERM openvpn
最后将 openvpn-startup.sh 和 openvpn-shutdown.sh 脚本添加到系统的 startup 和shutdown 脚本中 或拷贝到 /etc/init.d 目录.
管理多条 OpenVPN 隧道的 startup 和 shutdown
这里是一个/etc/init.d 下的脚本例子,它自动为 /etc/openvpn 下的每一个.conf 文件创建一条 OpenVPN 隧道。
该脚本在通过 RPM 安装 OpenVPN 时会缺省安装到机器上。
sample-scripts/openvpn.init
#!/bin/sh
#
openvpn This shell script takes care of starting and stopping
openvpn on RedHat or other chkconfig-based system.
#
chkconfig: 345 80 30
#
描述: OpenVPN is a robust and highly flexible tunneling application that
uses all of the encryption, authentication, and certification features
of the OpenSSL library to securely tunnel IP networks over a single
UDP port.
#
Contributed to the OpenVPN project by
Douglas Keller
2002.05.15
安装此脚本:
将这个文件拷贝到 /etc/rc.d/init.d/openvpn
shell> chkconfig –add openvpn
shell> mkdir /etc/openvpn
make .conf or .sh files in /etc/openvpn (see below)
删除此脚本:
运行: chkconfig –del openvpn
作者提示:
#
我已经写了一个 /etc/init.d 初始化脚本并修改了 openvpn.spec 可以自动注册该脚本。
RPM 包装好后你可以直接使用 “service openvpn start” 和 “service openvpn stop”.
命令启动和终止 OpenVPN.
#
初始化脚本工作如下:
#
- 为它在/etc/openvpn下找到的每一个 .conf 文件启动一个 openvpn 进程
#
- 如果存在对应于 xxx.conf 的 /etc/openvpn/xxx.sh 文件,
那么在它启动 openvpn 前执行它(作 openvpn –mktun… 时很有用)。
#
- 除 start/stop 外还可以执行:
#
service openvpn reload - SIGHUP
service openvpn reopen - SIGUSR1
service openvpn status - SIGUSR2
Modifications 2003.05.02
* Changed == to = for sh compliance (Bishop Clark).
* If condrestart|reload|reopen|status, check that we were
actually started (James Yonan).
* Added lock, piddir, and work variables (James Yonan).
* If start is attempted twice, without an intervening stop, or
if start is attempted when previous start was not properly
shut down, then kill any previously started processes, before
commencing new start operation (James Yonan).
* Do a better job of flagging errors on start, and properly
returning success or failure status to caller (James Yonan).
Location of openvpn binary
openvpn=”/usr/sbin/openvpn”
Lockfile
lock=”/var/lock/subsys/openvpn”
PID directory
piddir=”/var/run/openvpn”
Our working directory
work=/etc/openvpn
Source function library.
. /etc/rc.d/init.d/functions
Source networking configuration.
. /etc/sysconfig/network
Check that networking is up.
[ ${NETWORKING} = “no” ] && exit 0
[ -f $openvpn ] || exit 0
See how we were called.
case “$1” in
start)
echo -n $”Starting openvpn: “
/sbin/modprobe tun >/dev/null 2>&1
From a security perspective, I think it makes
sense to remove this, and have users who need
it explictly enable in their –up scripts or
firewall setups.
#echo 1 > /proc/sys/net/ipv4/ip_forward
if [ ! -d $piddir ]; then
mkdir $piddir
fi
if [ -f $lock ]; then
we were not shut down correctly
for pidf in /bin/ls $piddir/*.pid 2>/dev/null
; do
if [ -s $pidf ]; then
kill cat $pidf
>/dev/null 2>&1
fi
rm -f $pidf
done
rm -f $lock
sleep 2
fi
rm -f $piddir/*.pid
cd $work
Start every .conf in $work and run .sh if exists
errors=0
successes=0
for c in /bin/ls *.conf 2>/dev/null
; do
bn=${c%%.conf}
if [ -f “$bn.sh” ]; then
. $bn.sh
fi
rm -f $piddir/$bn.pid
$openvpn –daemon –writepid $piddir/$bn.pid –config $c –cd $work
if [ $? = 0 ]; then
successes=1
else
errors=1
fi
done
if [ $errors = 1 ]; then
failure; echo
else
success; echo
fi
if [ $successes = 1 ]; then
touch $lock
fi
;;
stop)
echo -n $”Shutting down openvpn: “
for pidf in /bin/ls $piddir/*.pid 2>/dev/null
; do
if [ -s $pidf ]; then
kill cat $pidf
>/dev/null 2>&1
fi
rm -f $pidf
done
success; echo
rm -f $lock
;;
restart)
$0 stop
sleep 2
$0 start
;;
reload)
if [ -f $lock ]; then
for pidf in /bin/ls $piddir/*.pid 2>/dev/null
; do
if [ -s $pidf ]; then
kill -HUP cat $pidf
>/dev/null 2>&1
fi
done
else
echo “openvpn: service not started”
exit 1
fi
;;
reopen)
if [ -f $lock ]; then
for pidf in /bin/ls $piddir/*.pid 2>/dev/null
; do
if [ -s $pidf ]; then
kill -USR1 cat $pidf
>/dev/null 2>&1
fi
done
else
echo “openvpn: service not started”
exit 1
fi
;;
condrestart)
if [ -f $lock ]; then
$0 stop
avoid race
sleep 2
$0 start
fi
;;
status)
if [ -f $lock ]; then
for pidf in /bin/ls $piddir/*.pid 2>/dev/null
; do
if [ -s $pidf ]; then
kill -USR2 cat $pidf
>/dev/null 2>&1
fi
done
echo “Status written to /var/log/messages”
else
echo “openvpn: service not started”
exit 1
fi
;;
*)
echo “Usage: openvpn {start|stop|restart|condrestart|reload|reopen|status}”
exit 1
esac
exit 0
用inetd或xinetd衍生(instantiate)一个 OpenVPN daemon
通用服务进程 xinetd 能够响应远端节点发送的初始数据报,自动衍生一个 OpenVPN daemon 。
此 xinetd 配置会使 xinetd 进程监听 UDP 端口 5000,当流入一个 OpenVPN session (使用 pre-shared key)的数据报时,xinetd 自动衍生一个 OpenVPN daemon来处理此 session。注意使用 –inactive 参数会使 OpenVPN daemon 在发呆10分钟后超时退出。无论何种原因一旦OpenVPN daemon 退出,xinetd 服务会重新监听端口等待新的连接。另外要注意 xinetd 使用 root 权限衍生 OpenVPN daemon,但随后(读取受保护的密钥文件后) OpenVPN 会将权限降为 nobody 。
可用如下命令生成密钥(key)文件:
openvpn –genkey –secret key
注意每一条新的 OpenVPN 隧道都有它独自的端口,同时也有它自己的 xinetd 配置文件。这是因为OpenVPN 对每一个潜在的接入者需要特定的信息,包括key文件,TUN/TAP 设备,隧道节点(endpoints),和路由配置。基于这种观点在 OpenVPN 的发展中,它从不使用单个配置文件来处理一大批类似的潜在接入者,即它没有描述接入的模板文件。从OpenVPN 作为一个UDP server 实现以来,它不具有TCP server可监听一个固定端口同时可 fork 一个新的 daemon 来动态处理客户连接的优点。尽管如此,接入模板的实现已进入预期计划,只要得到开发者和最终用户社区的足够注意和支持,它一定会实现的。
sample-config-files/xinetd-server-config
An xinetd configuration file for OpenVPN.
#
This file should be renamed to openvpn or something suitably
descriptive and copied to the /etc/xinetd.d directory.
xinetd can then be made aware of this file by restarting
it or sending it a SIGHUP signal.
#
For each potential incoming client, create a separate version
of this configuration file on a unique port number. Also note
that the key file and ifconfig endpoints should be unique for
each client. This configuration assumes that the OpenVPN
executable and key live in /root/openvpn. Change this to fit
your environment.
service openvpn_1
{
type = UNLISTED
port = 5000
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /root/openvpn/openvpn
server_args = –inetd –dev tun –ifconfig 10.4.0.2 10.4.0.1 –secret /root/openvpn/key –inactive 600 –user nobody
}
sample-config-files/xinetd-client-config
This OpenVPN config file
is the client side counterpart
of xinetd-server-config
dev tun
ifconfig 10.4.0.1 10.4.0.2
remote my-server
port 5000
user nobody
secret /root/openvpn/key
inactive 600
Copyright (C) 2002-2004 by James Yonan . 此文档于 GNU Free Documentation License Version 1.2 协议下发布.
中文翻译:liyi
Iptables 指南 1.1.19
SAFEARRAY(安全数组)使用详解
SAFEARRAY(安全数组)使用详解
一,何谓SAFEARRAY(安全数组):
winddows操作系统与使用 SAFEARRAY 定义。 下列 SAFEARRAY 结构是 SAFEARRAY 典型、 一般定义:
[cpp]
typedef struct FARSTRUCT tagSAFEARRAY { unsigned short cDims; // 安全数组的大小
unsigned short fFeatures; //安全数组的标记,取值见下表
#if defined(WIN32) //如果在windows系统上
unsigned long cbElements; //安全数组元素的大小 //不包括安全数组数据的大小
unsigned long cLocks; // 被锁定次数
#else
unsigned short cbElements;
unsigned short cLocks;
unsigned long handle; // 仅用在 Macintosh 系统上
#endif void HUGEP* pvData; // 数据指针
SAFEARRAYBOUND rgsabound[1]; //安全数组的下界,元素数, 结构见下说明 } SAFEARRAY;
typedef struct tagSAFEARRAYBOUND {
unsigned long cElements;// 元素数
long lLbound;// 数组的下界
} SAFEARRAYBOUND;
fFeatures; //安全数组的标记说明
FADF_AUTO 0x0001在栈上创建数组
FADF_STATIC 0x0002在堆上创建数组
FADF_EMBEDDED 0x0004在结构中创建
FADF_FIXEDSIZE 0x0010不能改变数组大小
FADF_RECORD 0x0020记录容器
FADF_HAVEIID 0x0040有IID 身份标记 数组
FADF_HAVEVARTYPE 0x0080VT 类型数组
FADF_BSTR 0x0100BSTR数组
FADF_UNKNOWN 0x0200IUnknown 数组
FADF_DISPATCH 0x0400IDispatch 数组
FADF_VARIANT 0x0800VARIANTs数组
FADF_RESERVED 0xF0E8余留,将来使用
[/cpp]
Microsoft Windows 2000 和 WindowsXP 等操作系统系统使用整个 Win32API。 因此, 是运行 Windows 2000 或 WindowsXP, 计算机上之后处理条件指令, Oaidl.h 文件与以下示例代码中可能定义 SAFEARRAY:
[cpp]
typedef struct tagSAFEARRAY {
USHORT cDims;
USHORT fFeatures;
ULONG cbElements;
ULONG cLocks;
PVOID pvData;
SAFEARRAYBOUND rgsabound[ 1 ];
} SAFEARRAY;
Oaidl.h 文件, 中 SAFEARRAYBOUND 是如以下示例代码中定义一个结构:
typedef struct tagSAFEARRAYBOUND {
unsigned long cElements;
long lLbound;
} SAFEARRAYBOUND;
[/cpp]
Oaidl.h 文件还包含对于, 可用于访问 SAFEARRAY 函数原型。
二,什么情况下使用
1:在使用vc编写COM组件的时候,需要一次传递很多的数据时,使用SAFEARRAY就会很方便
2:VisualBasic 和 C 之间或在 VisualBasic 和 VisualC++, 之间传递数组或字符串,用 C、 C++ 或 ATL 创建 DLL时用SAFEARRAY。
三,使用实例
1:使用SafeArrayAllocDescriptor在栈上创建一维数组
[cpp]
//创建SAFEARRAY数组,每个元素为long型,该数组是一维数组
long nData[10]={1,2,3,4,5,6,7,8,9,10};
SAFEARRAY* pArray=NULL;
HRESULT hr=SafeArrayAllocDescriptor(1,&pArray);//创建SAFEARRAY结构的对象
pArray->cbElements=sizeof(nData[0]);
pArray->rgsabound[0].cElements=10;
pArray->rgsabound[0].lLbound=0;
pArray->pvData=nData;
pArray->fFeatures=FADF_AUTO|FADF_FIXEDSIZE;//FADF_AUTO指定在栈上分配数据,并且大小不可以改变(固定为10)
//访问SAFEARRAY数组
long pValue=NULL;
SafeArrayAccessData(pArray,(void*)&pValue);//取得数据存到指针pValue
long Low(0),High(0);
hr=SafeArrayGetLBound(pArray,1,&Low);//维数索引从1开始
hr=SafeArrayGetUBound(pArray,1,&High);//维数索引从1开始
SafeArrayUnaccessData(pArray);
SafeArrayDestroy(pArray);
[/cpp]
这种方法在栈上分配数组元素所占的空间,即nData数组所用的空间
2:vc++创建dll, VisualBasic向dll中传数组
Vc++中创建dll工程StdDLL,把下边函数复制到cpp中
[cpp]
long declspec (dllexport) stdcall Func2(SAFEARRAY *ppsaMyArray) {
HRESULT hr;
HUGEP byte plData;
hr = SafeArrayAccessData(ppsaMyArray, (void HUGEP FAR)&plData);//取得数组数据
byte baa;
baa=plData[0];//第一个数据
SafeArrayUnaccessData(ppsaMyArray);//取消数据访问
SafeArrayDestroy(*ppsaMyArray);//销毁
return 2;
}
[/cpp]
将以下文本追加到 StdDLL.def 文件中现有文本:
Func2
VisualBasic中创建工程
添加以下声明代码,
Private Declare Function Func2 Lib”C:StdDLLDebugStdDLL.dll” (MyArray() As Long) As Long ‘注意文件路径和你机器的一致
添加 Command1命令按钮,把以下代码附加到 Command 1 _ Click 事件过程中
[cpp]Dim Result As Long Dim MyArrayOfLongs(3) As Long
MyArrayOfLongs(0) = 0
MyArrayOfLongs(1) = 1
MyArrayOfLongs(2) = 2
Result = Func2(MyArrayOfLongs())
MsgBox (“Func2 returned “ & Result) [/cpp]
四,注意问题
1) 在堆上创建SAFEARRAY数组
2) 一方创建,一方回收
3) 接收方不可以修改SAFEARRAY的数据,只能读或者销毁
首先介绍SafeArray使用,在介绍SafeArray中的结构。看完该节文章,SafeArray的陌生感一扫而去。
SafeArray 在ADO编程中经常使用。它的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成 SafeArray。实质上SafeArray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。SafeArray也并不单独使用,而是将其再包装到VARIANT类型的变量中,然后才作为参数传送出去。在VARIANT的vt成员的值如果包含VT_ARRAY|…,那么它所封装的就是一个SafeArray,它的parray成员即是指向SafeArray的指针。SafeArray中元素的类型可以是VARIANT能封装的任何类型,包括VARIANT类型本身。
使用SafeArray的具体步骤:
方法一:
包装一个SafeArray:
(1)定义变量,如:
VARIANT varChunk;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];
(2)创建SafeArray描述符:
//read array from a file.
uIsRead=f.Read(bVal,ChunkSize);
if(uIsRead==0)
break;
rgsabound[0].cElements = uIsRead;
rgsabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_UI1,1,rgsabound);
(3)放置数据元素到SafeArray:
for(long index=0;index<uIsRead;index++)
{
if(FAILED(SafeArrayPutElement(psa,&index,&bVal[index])))
::MessageBox(NULL,”出毛病了。”,”提示”,MB_OK | MB_ICONWARNING);
}
一个一个地放,挺麻烦的。
(4)封装到VARIANT内:
varChunk.vt = VT_ARRAY|VT_UI1;
varChunk.parray = psa;
这样就可以将varChunk作为参数传送出去了。
读取SafeArray中的数据的步骤:
(1)用SafeArrayGetElement一个一个地读
BYTE buf[lIsRead];
for(long index=0; index<lIsRead; index++)
{
::SafeArrayGetElement(varChunk.parray,&index,buf+index);
}
就读到缓冲区buf里了。
方法二:
使用SafeArrayAccessData直接读写SafeArray的缓冲区:
(1)读缓冲区:
BYTE *buf;
SafeArrayAccessData(varChunk.parray, (void **)&buf);
f.Write(buf,lIsRead);
SafeArrayUnaccessData(varChunk.parray);
(2)写缓冲区:
BYTE *buf;
::SafeArrayAccessData(psa, (void **)&buf);
for(long index=0;index<uIsRead;index++)
{
buf[index]=bVal[index];
}
::SafeArrayUnaccessData(psa);
varChunk.vt = VT_ARRAY|VT_UI1;
varChunk.parray = psa;
这种方法读写SafeArray都可以,它直接操纵SafeArray的数据缓冲区,比用SafeArrayGetElement和 SafeArrayPutElement速度快。特别适合于读取数据。但用完之后不要忘了调用::SafeArrayUnaccessData (psa),否则会出错的。
以下就是SAFEARRAY的Win32定义:
typedef struct tagSAFEARRAY
{
unsigned short cDims;
unsigned short fFeatures;
unsigned long cbElements;
unsigned long cLocks;
void * pvData;
SAFEARRAYBOUND rgsabound[ 1 ];
} SAFEARRAY;
这个结构的成员(cDims,cLocks等)是通过API函数来设置和管理的。真正的数据存放在pvData成员中,而SAFEARRAYBOUND结构定义该数组结构的细节。以下就是该结构成员的简要描述:
rgsabound是一个有趣的成员,它的结构不太直观。它是数据范围的数组。该数组的大小依safe array维数的不同而有所区别。rgsabound成员是一个SAFEARRAYBOUND结构的数组–每个元素代表SAFEARRAY的一个维。
typedef struct tagSAFEARRAYBOUND
{
unsigned long cElements;
unsigned long lLbound;
} SAFEARRAYBOUND;
维数被定义在cDims成员中。例如,一个\’C\’类数组的维数可以是[3][4][5]-一个三维的数组。如果我们使用一个SAFEARRAY来表示这个结构,我们定义一个有三个元素的rgsabound数组–一个代表一维。
cDims = 3;
…
SAFEARRAYBOUND rgsabound[3];
rgsabound[0]元素定义第一维。在这个例子中ILBOUND元素为0,是数组的下界。cElements成员的值等于三。数组的第二维 ([4])可以被rgsabound结构的第二个元素定义。下界也可以是0,元素的个数是4,第三维也是这样。
要注意,由于这是一个”C”数组,因此由0 开始,对于其它语言,例如Visual Basic,或者使用一个不同的开始。该数组的详细情况如下所示:
关于SAFEARRAYBOUND结构其实还有很多没说的。我们将要使用的SAFEARRAY只是一个简单的单维字节数组。我们通过API函数创建数组的时候,SAFEARRAYBOUND将会被自动设置。只有在你需要使用复杂的多维数组的时候,你才需要操作这个结构。
还有一个名字为cLocks的成员变量。很明显,它与时间没有任何的关系–它是一个锁的计数器。该参数是用来控制访问数组数据的。在你访问它之前,你必须锁定数据。通过跟踪该计数器,系统可以在不需要该数组时安全地删除它。
创建SAFEARRAY
创建一个单维SAFEARRAY的简单方法是通过使用SafeArrayCreateVector API函数。该函数可分配一个特定大小的连续内存块。
SAFEARRAY *psa;
// create a safe array to store the stream data
// llen is the number of bytes in the array.
psa = SafeArrayCreateVector( VT_UI1, 0, llen );
SafeArrayCreateVector API创建一个SAFEARRAY,并且返回一个指向它的指针。首个参数用来定义数组的类型–它可以是任何有效的变量数据类型。为了传送一个串行化的对 象,我们将使用最基本的类型–一个非负的字节数组。VT–UI1代表非负整形的变量类型,1个字节。
常数\’0\’定义数组的下界;在C++中,通常为0。最后的参数llen定义数组元素的个数。在我们的例子中,这与我们将要传送对象的字节数是一样的。我们还没有提数组大小(llen)是怎样来的,这将在我们重新考查串行化时提及。
在你访问SAFEARRAY数据之前,你必须调用SafeArrayAccessData。该函数锁定数据并且返回一个指针。在这里,锁定数组意味着增加该数组的内部计数器(cLocks)。
// define a pointer to a byte array
unsigned char *pData = NULL;
SafeArrayAccessData( psa, (void**)&pData );
… use the safe array
SafeArrayUnaccessData(psa);
相应用来释放数据的函数是SafeArrayUnaccessData(),该功能释放该参数的计数。
苹果VS谷歌(转自译言)
转自:http://article.yeeyan.org/view/176819/161611
当2006年苹果公司在曼哈顿的第五大道上开设了一家新的实体店时,它却受到了不同寻常的抱怨。以往在纽约,新建筑物收到的投诉通常都是因为你遮挡了我花重金购买的绝佳视野,或是你要升级改造我刚刚发现的地块,而是正如一位伊斯兰教的狂热者所抱怨的那样,这家立方体型的由钢制的透明的立苹果实体店对伊斯兰教是一种亵渎,因为它怎么看怎么像屹立在麦加圣城中的克尔白。
这个故事很无厘头–因为它出自某个极端网站上,那些聪明的狂热的宗教信徒说:”当这家店铺还在装修的时候,黑色的防雨布罩住这家点的顶棚好像麦加的克尔白。”对此,纽约很多的穆斯林曾站出来说过:“我们很喜爱这家苹果店。”但是回过头来看,将苹果商店比作麦加也并不疯狂。拥有漂亮内饰和外观的苹果商店,仿佛就是苹果产品拥护者的朝圣地。不像大多数的电子产品制造商,苹果公司销售的远不是造型设计流畅的电子玩具,而是一种生活的态度和方式,即“苹果主义”。
苹果主义并非是一种信仰,但是它却有着救世主般的领导者–史蒂夫乔布斯。充满传奇色彩的是,他在1985年被董事会解雇后,1997年重新走马上任,使业绩暴跌的苹果公司起死回生。许多苹果迷们对苹果公司满怀忠诚:10月辞世的美国影星托尼·柯蒂斯(Tony Curtis)将他的iPhone作为陪葬品,就像是一位法老渴望在来世继续更新Facebook状态一样。
关注狂热的追随者,对于许多信仰来说都是一件非常有趣但启示性并不大的事情。最近一次去第五大道的苹果商店,发现许多苹果信徒并非传统意义上的苹果迷:时髦,富有的西方青年。取而代之的是衣领上带阿联酋国旗的外交官模样的人;一群来自巴西的用葡萄牙语嬉戏打闹(horesed around)的男孩儿们;放下手中的《福音圣经》,玩起了网游《Combat Arm》的红发年轻人;还有一对中年夫妇,正在访问一家名为Bed, Bath & Beyond的购物网站。苹果过去的的成功只局限于那些穿不对称牛仔裤、带黑框眼镜的人群,而如今它已经超越了这一范畴,开始迈向大众市场。
商店内,大多数设备都可以拿在手里把玩试用。这就是苹果公司的一招智慧的棋子:虽然这会对商品产生一定的浪费,但是它也吸引了那些潜在的买家,使苹果商店犹如过去的唱片店一样,成为了人们闲逛的好去处。只有一个地方被里三层外三层围的水泄不通,那就iPad展台。
iPad,这款苹果今年4月发布的平板电脑,已经成为了一种现象。尽管早期遭遇了一些质疑,尽管没有3G模块的版本售价仍然高达500美元,尽管并不具备多少其他设备(电子阅读器、游戏机以及苹果自家的iPhone手机)所缺乏的功能,但该产品上市6个月的销量仍然高达750万台。iPad符合苹果一贯的大胆作风,它创造出了一类全新的产品,而人们之所以买账,几乎完全是因为它出自苹果。苹果已于2007年停用“苹果电脑”这一公司名称,如今的苹果已经在 Mac电脑以外,拥有了3款主打产品——iPod、iPad和iPhone。它想随时对地与你同在。
这也使得苹果与另外一家企业产生了冲突,这家企业原本并不开发移动设备,但如今却想时时伴你左右。谷歌起家时,专门为用户提供更为智能的互联网搜索方式;现在,它的业务范围遍及各种服务,而且已经渗透到我们生活的方方面面。我们会利用谷歌搜索一家好饭店,搜索它在其他网站上的评论,在谷歌地图上寻找它的位置,搜索列车是否准时,并用Gmail告知好友,我们可能会晚15分钟。
逐渐地,我们可能会通过搭载谷歌Android操作系统的智能手机来完成上述所有事情。谷歌自己并不生产手机,但是随着它将Android授权给越来越多的手机厂商,这样一家根本不生产任何消费电子产品的企业,却已经成为全球最成功消费电子企业的最大竞争对手。谷歌下了很大的赌注,希望创造同样能让我们时刻铭记的“谷歌主义”(Googleism)。
但事情并不总是一成不变的。仅仅一两年前,苹果和谷歌还相安无事,而谷歌CEO埃里克·施密特(Eric Schmidt)也得以稳坐苹果董事会(2006年至2009年)。“史蒂夫和我是非常好的私人朋友,”施密特今年夏天说,“我相信,无论以何种标准评判,他都是全世界最优秀的CEO。”这两家公司本应是“天作之合”:苹果的华丽设备运行谷歌神奇的服务。但是智能手机的吸引力令谷歌难以割舍。在2010 年末的销量超越iPhone后,Android如今已经成为最畅销的智能手机操作系统。乔布斯暗示,谷歌已经违反了双方心照不宣的“互不侵犯条约”。他在今年6月的一次会议上说:“我们不想进军搜索”,而且“我们也不会进军搜索”。乔布斯的自信一如既往,他当时对台下的听众表示,他不会从苹果的设备中移除谷歌的搜索框。“现在,我们有了更好的产品。”他说。
在移动大战中,这两家公司采取了截然不同的方法。苹果的设备只能安装通过苹果认证的应用。而谷歌则通过免费方式,将Android安装到了索尼、摩托罗拉、三星、LG、宏达电等手机厂商的数十款设备上。Android代码是开源的,手机厂商可以通过修改,使之适应自己的需求(尽管谷歌试图维护一套基本的标准,以便让针对一款Android手机开发的应用也可以兼容其他Android手机)。任何人开发的Android应用都可以进驻 Android Market,这是一个与苹果应用商店对应的服务。苹果的产品很华丽,但是却更为封闭。施密特今年7月造访《经济学人》伦敦总部时,曾经谈到了二者之间的这一差异。“谷歌采取了完全不同的模式,”他说,“苹果的观念一贯都很封闭。我们则采取了相反的模式:网络、开放、所有的选择、所有的声音。而且这一实验还在进行之中。”
把一家公司的老板打造成为该公司的文化标志,这种伎俩似乎已经过时,但是这两家公司的领导人却都拥有令人无法抗拒的诱惑。作为苹果无可争议的导航灯,乔布斯是一名出众且难于捉摸的人。他一贯蔑视媒体,除非是在指导公关团队“泄露”信息,或是举行规模盛大的新闻发布会时。他日复一日地穿着同一套行头(一件黑色高领衫和一条李维斯501牛仔裤),一如网上流传的乔布斯玩偶。乔布斯领导下的苹果几乎从未推出过没有价值的产品。
相比而言,谷歌没有乔布斯,但却拥有古怪的三家马车——CEO施密特以及联合创始人拉里·佩奇(Larry Page)和赛吉·布林(Sergy Brin)。佩奇和布林是斯坦福大学的同学,至今仍在推动谷歌的创新,并将公司的日常运营事务托付给施密特,一位西装革履的CEO。谷歌可以对用户的电子邮件、网络搜索和手机进行研究,然后再卖给广告主,借此获取收入。谷歌成立时的信条是“不作恶”,它的员工至今仍在身体力行。但是施密特似乎又有了一条新的标准:“不令人生厌。”他2009年的一番言论令评论人士大跌眼镜:“如果你有什么不希望别人知道的事情,当初就不应该干。”显然是为了安抚那些担心谷歌做事没有底线的人,他2010年末又再度阐述了自己的观点,他说:“谷歌的政策是到达令人生厌的那条底线,但不会逾越。”但他显然没有意识到,对于一家无处不在的科技公司的老板而言,这恰恰是他所能说出的最令人厌恶的话。
与苹果相比,谷歌是一个不讲规则的地方,它倾向于把产品先发布出去,然后再观察外界的反应。Gmail,一款获得了巨大成功的电子邮件系统,以测试版的形式发布,并且将这个标签保留了多年。Wave,一款极其复杂的电子邮件、信息和协作工具,用户却寥寥无几。Buzz,一款社交网络工具,由于对外公开了用户的常用联系人而遭遇了一场隐私灾难。这就是谷歌的产品开发过程,这里鼓励员工每周拿出一天来研究个人项目,而相对于设计师那精美的作品而言,程序员采用的试探性方法更受器重。
尽管存在种种差异,但谷歌和苹果却都发源于同一片土壤:加州硅谷。这两家公司的故事表明,一家公司的许多工程师和程序员原本都可以到另外一家公司工作:上世纪80年代在办公室里玩塑胶球的苹果Mac创造者,完全可能成为谷歌的创始人,并在90年代末利用乐高积木搭建服务器机架。硅谷可能是世界上最具创意的地方,这里诞生和毁灭过大量的企业,正因如此,才催生出一种“别告诉我从来没人试过”的态度,并同时推动着苹果和谷歌的发展。
但这两家公司却都在初期就开始展现他们的发展方向。乔布斯说,他在大学(退学前)上的最重要的课就是书法。在内心深处,他已然成为了一名设计师,于是他领导了一支团队开发出首款Macintosh电脑。当其他团队成员夜以继日地提高性能时,乔布斯却在对外观吹毛求疵,努力改进那些其他人几乎没有注意到的细微之处。尽管今天看来,当年的第一款Mac电脑有些笨重,色彩也不够鲜活,但在1984年,它却堪称设计典范。这是全球首款配备屏幕的商用电脑,外观与我们现在使用的电脑别无二致。
谷歌的DNA也在早期就已经展现。佩奇当年曾经对一名导师说,他想将整个互联网都下载到他的电脑中。谷歌的野心由此可见一斑。他们购买了大量的廉价电脑,并将其连为一体,这也成为谷歌得以成型的关键:但在多数外部人士看来,谷歌的成功更多地体现在软件上,而非硬件工程。如今,谷歌每天都要处理 10亿次以上的搜索,可是你上次看到它崩溃是在什么时候?
这两家公司都曾经是无名小卒:苹果曾经是希望挑战微软的大卫,而谷歌也曾是希望推翻雅虎王朝的后起之秀。他们都非常优异,并逐渐发展壮大,随后一路披荆斩棘进军了新的领域,推出了新的产品。现在,苹果和谷歌在浏览器(Safari和Chrome)、图片编辑软件(iPhoto和 Picasa)、电子邮件(Me.com和Gmail)以及云计算(MobileMe和iGoogle)等领域展开了竞争。苹果iTunes是当今全球最大的音乐商店;谷歌则通过谷歌音乐予以回应。几年前还对图书业务嗤之以鼻的苹果,如今也开始通过iTunes出售电子书了;谷歌也在通过谷歌图书项目悄悄对所有能拿到手的书籍进行数字化。谷歌拥有全球最大的视频网站YouTube;苹果也开始(借助iTunes、iPod、iPad和Apple TV)将提供电影作为核心业务。今年4月,苹果反戈一击,针对谷歌的核心业务推出了iAd,一款移动广告平台。
《呆伯特》(Dilbert)连环画的创造者斯科特·亚当斯(Scott Adams)开设了一个博客,主要针对技术人员发表评论。去年,他曾经将依赖技术的人称作是“电子人”(cyborg):“如果一个电子人能够把电子眼取下,放在架子上当监视器用,我想我们都认为它的确能做到,那么你的手机就有资格成为你身体的一部分。”他将手机视为人的“外脑”:“你将大脑的部分记忆外包给外脑,并利用外脑来提供其他一些功能,例如GPS导航,或者搜索互联网。如果你像我一样,你的外脑就会每天24小时伴随着你。”
如果智能手机能够成为我们的外脑,至少在未来几年内,苹果或谷歌将会成为多数外脑的幕后主导者。微软Windows Phone 7的希望比较渺茫。只有黑莓,一款以工作为中心的、与众不同的设备有可能与他们一较高下。除此之外,其他企业也只能是跟随者谷歌和苹果的步伐而已。
当然,苹果和谷歌在构建外脑的过程中,采取了截然不同的方法。外界虽然对苹果系统的封闭颇有微词,但它的确提供了一系列优秀的设备。 iPod、 iPad和iPhone都是Mac的延伸,可以将图片、视频、音乐和电影融合成一条快乐的河流,无论在火车上、沙发上还是行走过程中,我们都可以畅游其中。由于使用了与iPod和iPhone相同的iOS系统,iPad也拥有了数亿名已经熟悉其使用方法的潜在用户。苹果提供的外脑是漂亮的硬件和直观的软件,多数时候,“亵玩”的乐趣甚至胜过“远观”。
但缺陷,同时也是苹果不希望你考虑的事情是:当你终于进入了它的手掌后,再要改变主意,就很难逃离苹果的系统。你通过苹果购买的音乐和电影只能借助一种蹩脚的权宜之计,从iPod转移到第三方设备,就连这种方法也是最近才刚刚出现的。苹果的产品几乎从不令你失望,可一旦你真的失望了,也已经为时已晚,这时的你已经付出了很多成本,并且拥有了一个“苹果主义者”的名声,尽管你不希望被这样称呼。作为iPhone美国独家运营商,AT&T 遭到很多苹果粉丝的诟病,但他们却别无选择。苹果主义的魔力如此强烈,以至于多数用户根本不在乎他们的iPhone其实是一款差劲的手机。乔布斯声称,任何网络都会像AT&T一样,被热切的iPhone用户淹没。他很快就可以更好地证明这一观点,因为iPhone明年就将与第二家美国运营商 (Verizon)签约。
谷歌追求的则是一种不同的品牌信仰。你可以选择运营商,也可以选择手机制造商。独立应用开发商可以通过不懈的努力将应用推向你的手机,而无需经过谷歌的批准。随着Android阵营的不断壮大,互联网以及网民的群体智慧将推动这些应用不断改进。谷歌本身则几乎一无所求。它不会像苹果那样直接对你收费,也不会向你销售外脑,它想要的是内容。
有了这些内容,它就可以向那些想对你发布广告的企业收费。这都是些小广告,不是吗?谷歌早先曾承诺,所有的广告都是文本广告,而且篇幅很短。由于广告都是为你量身定制的,所以你不会感觉被打扰,也没有任何损失。
这些量身定制的广告有时会很滑稽:一名大学生写了一篇有关板球的文章,文中提到了灰烬杯(Ashes),于是他的搜索结果一侧便会出现火葬场的广告。但是它的风险却不止于此。去年在纽约举行的一次会议上,我遇到了一位令人印象深刻的将军,他极度自信,当时任职于美国特种部队,而且参加过伊拉克战争。我们聊了一会,并且交换了名片,我并没有将这件事放在心上。但一年后,当我上网冲浪时,他却反复出现在谷歌的广告中。他当时正在竞选密苏里州的国会议员,而我则完全无法逃脱他的竞选广告。我并不住在密苏里,但是谷歌似乎通过某种渠道知道了我曾经见过他。
当它们在你的口袋中发生冲突之前,苹果主义和谷歌主义都曾赢得过你的信赖。苹果彻底改变了我们对电子产品的认识。美国《Fast Company》杂志的设计编辑克里夫·库昂(Cliff Kuang)说,以前,当一款新的电子产品面市时,“你家里只有一个人知道怎么用。而苹果已经彻底改变了这种状况。不会再有人认为,要使用苹果的产品还用学。”
事实上,我的新iPad根本没有说明书和使用手册,也没有乱七八糟的电线和数据线,甚至连光盘都没有。打开包装后,看到的只有iPad和一条数据线。无需阅读晦涩的说明,只要把iPad拿出来,揭下上面的塑料膜,按一下按钮,就会出现“欢迎。你想要做什么?”的语音提示。这种易用性或许可以帮助乔布斯为AT&T辩护:根据美国权威杂志《消费者报告》的数据,iPhone用户的数据使用量比其他智能手机用户多五倍。苹果主义者并不是在摆弄他们的苹果设备,而是在实实在在地使用。
而且,苹果的产品经常会被用于“google”信息。值得注意的是“apple”并未成为动词。我们已经忘记,在苹果将电脑和电子产品引入主流前,这些设备曾经是多么地难于使用。与之类似,很多人也已经忘记,在谷歌诞生前,搜索引擎同样非常糟糕。当时的大型互联网公司都希望成为门户——通过一个单独的网页为你提供媒体、购物机会、天气预报以及电子邮件等服务。但是雅虎、AltaVista、Excite等企业却无法组织数百万的网页。谷歌则抛弃了门户的概念,而是利用神奇的算法挖掘用户在网上寻找什么,而且每次都能将这些内容放在搜索页面的顶部,或接近顶部的位置。有了谷歌,互联网才得以成为今天的样子。当然,它此后也推出了一些华而不实的页面,并且开始滥用先发优势。现在的网站都希望提升在谷歌中的排名,如果被挤到了第四页,几乎就没有任何被人发现的希望。迎合谷歌的算法已经成为零售商、娱乐明星和政治人物的重要任务,他们都在争夺搜索页面排名第一的位置。
苹果也能够令优秀的人或物锦上添花。过去20年间,iTunes给音乐行业带来的活力超过了任何一家公司。2010年2月,iTunes出售的歌曲已经达到了100亿首。在纽约或伦敦的地铁中,有半数乘客的耳朵里都塞着苹果的白色耳机。但他们并没有改变消费模式,而是承袭并加剧了原有的模式。下载模式在打压专辑销量的同时,却对热门单曲起到了推动作用。根据英国音乐版权协会(PRS for Music)的数据,2005年,排名首位的单曲平均销量为6万份,而目前的这一数字则达到了9.3万。有人曾经认为,由于获取大量音乐的成本降低,因此将增加一些非着名的小众音乐的销量。由《连线》杂志主编克里斯·安德森(Chris Anderson)提出的“长尾理论”认为,尽管20%的歌曲或书籍或者其他任何东西能够占到80%的销量,但小众市场仍然拥有很大的机会。但是英国音乐版权协会却发现,实际占到80%销量的歌曲只有2%。
无论是对苹果还是谷歌而言,只是帮助强者更强,根本称不上是一家优秀的企业。但是由于拥有强大的实力,无论他们做什么,都难免会成为批评的对象。但也并非全无变化,谷歌正在逐渐抛弃以往的做法,不再为所有用户提供完全相同的搜索结果,而是逐渐开始根据地理位置、浏览历史甚至联系方式,为不同用户提供个性化的结果。它希望可以借此提高搜索结果的相关性。部分媒体观察人士认为,生活在你自己的“谷歌泡泡”里,会威胁到文化,甚至民主,原因是用户永远不会被意外信息所“打扰”。目前为止,不同用户间的搜索引擎只有细微的差别。可以推测,施密特并不认为此举令人生厌。
种种迹象显示,苹果和谷歌正在展开一场殊死搏斗,尽管如此,他们仍然可以保持亦敌亦友的状态。很多人都用Gmail收发邮件,用iTunes 购买音乐,用iPod配合健身,并用Android接打电话。谷歌仍然是iPhone的默认搜索引擎。而刚刚开始崭露头角的Android平板电脑也将紧追 iPad的步伐,一如Android手机对iPhone的追赶一样。我们的屏幕世界非常宽广,远不止这两家公司,还包括主打图书和电子阅读器的亚马逊,提供社交网络的Facebook和Twitter,以及发布分类广告的eBay和Craigslist。无论是苹果还是谷歌,都没有足够的实力一统天下。
但苹果和谷歌在我们的口袋里展开的手机大战,却是苹果和微软的桌面大战以来,科技行业最大的一场冲突。到2011年底,智能手机的销量将超过传统手机,2012年则会超过PC。以往,照片、歌曲、文档和其他所有数据都是存储于个人设备上的,但这种系统却有可能会被云计算取代。与此同时,部分观察人士预计,搜索引擎收入很快也将见顶。乔布斯就是这些观察人士中的一员,他曾经直截了当地表示:“在移动设备中,搜索未成气候。搜索并非它的重点所在。” 这使得智能手机应用成为访问云计算的重要途径——而苹果和谷歌都在努力通过工作、浏览、听觉、视觉和网络产品,渗透到我们生活的方方面面,以便追赶彼此的收入。
他们的方法有着显着的差别。尽管竞争可能同时促进双方的发展,但要获得同等成功,可能性却微乎其微。世界将分成两派:一派是像苹果一样的完美主义者,他们遵循井然有序、一切尽在掌握的行为方式;还有一派则像谷歌一样勇于探索,他们反应迅速,而且信仰开放的模式。为数不多的完美产品由苹果生产,而数量庞大的Android设备则由谷歌来引导。伴着Facebook成长起来的一代人会忘记隐私担忧,最终投靠谷歌吗?那些成长过程中一直期待着设备够用即可的人会倾向苹果吗?答案不仅取决于金钱的多少,还取决于我们感受周围世界的方式。
Hello world!
欢迎使用 WordPress。这是系统自动生成的演示文章。编辑或者删除它,开始您的博客!
RedHat(CentOS)和Ubuntu安装软件命令对比(区别)
此表内容来自《Ubuntu Server最佳方案》,CentOS和Ubuntu(Debian)是VPS最常见的系统,这份表很实用,分享下。