tcpdump是一个用于截取网络分组,并输出分组内容的工具。tcpdump凭借强大的功能和灵活的截取策略,使其成为类UNIX系统下用于网络分析和问题排查的首选工具。 

tcpdump提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具。tcpdump存在于基本的Linux系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息。因此系统中存在网络分析工具主要不是对本机安全的威胁,而是对网络上的其他计算机的安全存在威胁。

选项

  • -A 以ASCII格式打印出所有分组,并将链路层的头最小化。 
  • -c 在收到指定的数量的分组后,tcpdump就会停止。 
  • -C 在将一个原始分组写入文件之前,检查文件当前的大小是否超过了参数file_size 中指定的大小。如果超过了指定大小,则关闭当前文件,然后在打开一个新的文件。参数 file_size 的单位是兆字节(是1,000,000字节,而不是1,048,576字节)。 
  • -d 将匹配信息包的代码以人们能够理解的汇编格式给出。 
  • -dd 将匹配信息包的代码以c语言程序段的格式给出。 
  • -ddd 将匹配信息包的代码以十进制的形式给出。 
  • -D 打印出系统中所有可以用tcpdump截包的网络接口。 
  • -e 在输出行打印出数据链路层的头部信息。 
  • -E 用spi@ipaddr algo:secret解密那些以addr作为地址,并且包含了安全参数索引值spi的IPsec ESP分组。 
  • -f 将外部的Internet地址以数字的形式打印出来。 
  • -F 从指定的文件中读取表达式,忽略命令行中给出的表达式。 
  • -i 指定监听的网络接口。 
  • -l 使标准输出变为缓冲行形式,可以把数据导出到文件。 
  • -L 列出网络接口的已知数据链路。 
  • -m 从文件module中导入SMI MIB模块定义。该参数可以被使用多次,以导入多个MIB模块。 
  • -M 如果tcp报文中存在TCP-MD5选项,则需要用secret作为共享的验证码用于验证TCP-MD5选选项摘要(详情可参考RFC 2385)。 
  • -b 在数据-链路层上选择协议,包括ip、arp、rarp、ipx都是这一层的。
  • -n 不把网络地址转换成名字。
  • -nn 不进行端口名称的转换。
  • -N 不输出主机名中的域名部分。例如,‘nic.ddn.mil‘只输出’nic‘。 
  • -t 在输出的每一行不打印时间戳。 
  • -O 不运行分组分组匹配(packet-matching)代码优化程序。 
  • -P 不将网络接口设置成混杂模式。 
  • -q 快速输出。只输出较少的协议信息。 
  • -r 从指定的文件中读取包(这些包一般通过-w选项产生)。 
  • -S 将tcp的序列号以绝对值形式输出,而不是相对值。 
  • -s 从每个分组中读取最开始的snaplen个字节,而不是默认的68个字节。 
  • -T 将监听到的包直接解释为指定的类型的报文,常见的类型有rpc远程过程调用)和snmp(简单网络管理协议;)。 
  • -t 不在每一行中输出时间戳。 
  • -tt 在每一行中输出非格式化的时间戳。 
  • -ttt 输出本行和前面一行之间的时间差。 
  • -tttt 在每一行中输出由date处理的默认格式的时间戳。 
  • -u 输出未解码的NFS句柄。 
  • -v 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息。 
  • -vv 输出详细的报文信息。 
  • -w 直接将分组写入文件中,而不是不分析并打印出来。

自 17.05 版本开始,Docker 支持多步骤镜像创建( Multi-stage build)特性,可以精简最终生成的镜像大小 。

对于需要编译的应用(如 CGoJava语言等)来说,通常情况下至少需要准备两个 环境的 Docker镜像:

  • 编译环境镜像 : 包括完整的编译引擎、依赖库等,往往比较庞大。作用是编译应用为二进制文件;
  • 运行环境镜像: 利用编译好的二进制文件,运行应用,由于不需要编译环境,体积比较小。

使用多步骤创建,可以在保证最终生成的运行环境镜像保持精筒的情况下,使用单一的Dockerfile,降低维护复杂度 。

Go语言应用为例。创建干净目录,进入到目录中,创建main.go文件,内容为:

// main.go will output "Hello, Docker"
package main

import ("fmt")

func main() {
    fmt.println("Hello, Docker")
}

创建 Dockerfile,使用 golang:1.9镜像编译应用二进制文件为 app,使用精简的镜像 alpine:latest 作为运行环境 。Dockerfile 完整内容为:

FROM golang:1.9 as builder # define stage name as builder
RUN mkdir -p /go/src/test
WORKDIR /go/src/test
COPY main.go
RUN CGO_ENABLED=O GOOS=linux go build -o app

FROM alpine:latest
RUN apk –no-cache add ca-certificates
WORKDIR /root/
COPY –from=builder /go/src/test/app . # copy file from the builder stage
CMD ["./app"]

执行如下命令创建镜像,并运行应用:

$ docker build -t yeasy/test multistage:latest .
Sending build context to Docker daemon 3.072kB
Step 1/10 : FROM golang:1.9
Successfully built 5fd0cb93dda0
Successfully tagged yeasy/test-multistage:latest 
$ docker run --rm yeasy/test-m ultistage:latest
Hello, Docker

查看生成的最终镜像,大小只有 6.55 MB:

$docker images | grep test-multistage
yeasy/test-multistage latest 5fd0cb93dda0 1 minutes ago 6.55MB

文章来源:

《Docker技术入门与实践》第三版 杨保华、戴王剑、曹亚仑 编著

1. dd命令

dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。

注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512;c=1; k=1024;w=2

参数注释:

  1. if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
  2. of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
  3. ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
    obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
    bs=bytes:同时设置读入/输出的块大小为bytes个字节。
  4. cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
  5. skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
  6. seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
    注意:通常只用当输出文件是磁盘或磁带时才有效,即备份到磁盘或磁带时才有效。
  7. count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
  8. conv=conversion:用指定的参数转换文件。
    • ascii:转换ebcdic为ascii
    • ebcdic:转换ascii为ebcdic
    • ibm:转换ascii为alternate ebcdic
    • block:把每一行转换为长度为cbs,不足部分用空格填充
    • unblock:使每一行的长度都为cbs,不足部分用空格填充
    • lcase:把大写字符转换为小写字符
    • ucase:把小写字符转换为大写字符
    • swab:交换输入的每对字节
    • noerror:出错时不停止
    • notrunc:不截短输出文件
    • sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

2. dd应用实例

1. 将本地的/dev/hdb整盘备份到/dev/hdd

$ dd if=/dev/hdb of=/dev/hdd

2. 将/dev/hdb全盘数据备份到指定路径的image文件

$ dd if=/dev/hdb of=/root/image

3. 将备份文件恢复到指定盘

$ dd if=/root/image of=/dev/hdb

4. 备份/dev/hdb全盘数据,并利用gzip工具进行压缩,保存到指定路径

$ dd if=/dev/hdb | gzip > /root/image.gz

5. 将压缩的备份文件恢复到指定盘

$ gzip -dc /root/image.gz | dd of=/dev/hdb

6. 备份与恢复MBR

备份磁盘开始的512个字节大小的MBR信息到指定文件:

$ dd if=/dev/hda of=/root/image count=1 bs=512

count=1指仅拷贝一个块;bs=512指块大小为512个字节。

恢复:

$ dd if=/root/image of=/dev/had

将备份的MBR信息写到磁盘开始部分

7. 备份软盘

$ dd if=/dev/fd0 of=disk.img count=1 bs=1440k (即块大小为1.44M)

8. 拷贝内存内容到硬盘

$ dd if=/dev/mem of=/root/mem.bin bs=1024 (指定块大小为1k)

9. 拷贝光盘内容到指定文件夹,并保存为cd.iso文件

$ dd if=/dev/cdrom(hdc) of=/root/cd.iso

10. 增加swap分区文件大小

第一步:创建一个大小为256M的文件:

$ dd if=/dev/zero of=/swapfile bs=1024 count=262144

第二步:把这个文件变成swap文件:

$ mkswap /swapfile

第三步:启用这个swap文件:

$ swapon /swapfile

第四步:编辑/etc/fstab文件,使在每次开机时自动加载swap文件:

$ /swapfile swap swap default 0 0

11. 销毁磁盘数据

$ dd if=/dev/urandom of=/dev/hda1

注意:利用随机的数据填充硬盘,在某些必要的场合可以用来销毁数据。

12. 测试硬盘的写速度

$ dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

通过以上命令输出的命令执行时间,可以计算出硬盘的写速度。

13. 测试硬盘的读速度

$ dd if=/root/1Gb.file bs=64k | dd of=/dev/null

通过以上命令输出的命令执行时间,可以计算出硬盘的读速度。

14. 确定硬盘的最佳块大小

$ dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file
$ dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file
$ dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file
$ dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

通过比较以上命令输出中所显示的命令执行时间,即可确定系统最佳的块大小。

15. 修复硬盘

$ dd if=/dev/sda of=/dev/sda

或者

$ dd if=/dev/hda of=/dev/hda

当硬盘较长时间(一年以上)放置不使用后,磁盘上会产生magnetic flux point,当磁头读到这些区域时会遇到困难,并可能导致I/O错误。当这种情况影响到硬盘的第一个扇区时,可能导致硬盘报废。上边的命令有可能使这些数 据起死回生。并且这个过程是安全、高效的。

16. 利用netcat远程备份

$ dd if=/dev/hda bs=16065b | netcat < targethost-IP > 1234

在源主机上执行此命令备份/dev/hda

netcat -l -p 1234 | dd of=/dev/hdc bs=16065b

在目的主机上执行此命令来接收数据并写入/dev/hdc

$ netcat -l -p 1234 | bzip2 > partition.img
$ netcat -l -p 1234 | gzip > partition.img

以上两条指令是目的主机指令的变化分别采用bzip2、gzip对数据进行压缩,并将备份文件保存在当前目录。

17. 将一个很大的视频文件中的第i个字节的值改成0x41(也就是大写字母A的ASCII值)

$ echo A | dd of=bigfile seek=$i bs=1 count=1 conv=notrunc

3. /dev/null和/dev/zero的区别

  • /dev/null,外号叫无底洞,你可以向它输出任何数据,它通吃,并且不会撑着!它是空设备,也称为位桶(bit bucket)。任何写入它的输出都会被抛弃。如果不想让消息以标准输出显示或写入文件,那么可以将消息重定向到位桶。
  • /dev/zero,是一个输入设备,你可你用它来初始化文件。该设备无穷尽地提供0,可以使用任何你需要的数目——设备提供的要多的多。他可以用于向设备或文件写入字符串0。

Link: http://www.linuxde.net/2013/03/12928.html

Introduction

A virtual private network, or VPN, allows you to securely encrypt traffic as it travels through untrusted networks, such as those at the coffee shop, a conference, or an airport.

IKEv2, or Internet Key Exchange v2, is a protocol that allows for direct IPSec tunneling between the server and client. In IKEv2 VPN implementations, IPSec provides encryption for the network traffic. IKEv2 is natively supported on some platforms (OS X 10.11+, iOS 9.1+, and Windows 10) with no additional applications necessary, and it handles client hiccups quite smoothly.

In this tutorial, you’ll set up an IKEv2 VPN server using StrongSwan on an Ubuntu 18.04 server and connect to it from Windows, macOS, Ubuntu, iOS, and Android clients.

Prerequisites

To complete this tutorial, you will need:

One Ubuntu 18.04 server configured by following the Ubuntu 18.04 initial server setup guide, including a sudo non-root user and a firewall.

Step 1 Installing StrongSwan

First, we’ll install StrongSwan, an open-source IPSec daemon which we’ll configure as our VPN server. We’ll also install the public key infrastructure component so that we can create a certificate authority to provide credentials for our infrastructure.

Update the local package cache and install the software by typing:

$ sudo apt update
$ sudo apt install strongswan strongswan-pki ufw

Now that everything’s installed, let’s move on to creating our certificates.

Step 2 Creating a Certificate Authority

An IKEv2 server requires a certificate to identify itself to clients. To help us create the certificate required, the strongswan-pki package comes with a utility to generate a certificate authority and server certificates. To begin, let’s create a few directories to store all the assets we’ll be working on. The directory structure matches some of the directories in /etc/ipsec.d, where we will eventually move all of the items we create. We’ll lock down the permissions so that our private files can’t be seen by other users:

$ mkdir -p ~/pki/{cacerts,certs,private}
$ chmod 700 ~/pki

Now that we have a directory structure to store everything, we can generate a root key. This will be a 4096-bit RSA key that will be used to sign our root certificate authority.

Execute these commands to generate the key:

ipsec pki --gen --type rsa --size 4096 --outform pem \
> ~/pki/private/ca-key.pem

Now that we have a key, we can move on to creating our root certificate authority, using the key to sign the root certificate:

$ ipsec pki --self --ca --lifetime 3650 --in ~/pki/private/ca-key.pem \
    --type rsa --dn "CN=VPN root CA" --outform pem > ~/pki/cacerts/ca-cert.pem

You can change the distinguished name (DN) values to something else to if you would like. The common name here is just the indicator, so it doesn’t have to match anything in your infrastructure.

Now that we’ve got our root certificate authority up and running, we can create a certificate that the VPN server will use.

Step 3 Generating a Certificate for the VPN Server

We’ll now create a certificate and key for the VPN server. This certificate will allow the client to verify the server’s authenticity using the CA certificate we just generated.

First, create a private key for the VPN server with the following command:

$ ipsec pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/server-key.pem

Now, create and sign the VPN server certificate with the certificate authority’s key you created in the previous step. Execute the following command, but change the Common Name (CN) and the Subject Alternate Name (SAN) field to your VPN server’s DNS name or IP address:

$ ipsec pki --pub --in ~/pki/private/server-key.pem --type rsa \
    | ipsec pki --issue --lifetime 1825 \
        --cacert ~/pki/cacerts/ca-cert.pem \
        --cakey ~/pki/private/ca-key.pem \
        --dn "CN=server_domain_or_IP" --san "server_domain_or_IP" \
        --flag serverAuth --flag ikeIntermediate --outform pem \
    >  ~/pki/certs/server-cert.pem

Now that we’ve generated all of the TLS/SSL files StrongSwan needs, we can move the files into place in the /etc/ipsec.d directory by typing:

$ sudo cp -r ~/pki/* /etc/ipsec.d/

In this step, we’ve created a certificate pair that would be used to secure communications between the client and the server. We’ve also signed the certificates with the CA key, so the client will be able to verify the authenticity of the VPN server using the CA certificate. Now that have all of the certificates ready, we’ll move on to configuring the software.

Step 4 Configuring StrongSwan

StrongSwan has a default configuration file with some examples, but we will have to do most of the configuration ourselves. Let’s back up the file for reference before starting from scratch:

$ sudo mv /etc/ipsec.conf{,.original}

Create and open a new blank configuration file by typing:

sudo vim /etc/ipsec.conf

First, we’ll tell StrongSwan to log daemon statuses for debugging and allow duplicate connections. Add these lines to the file:

config setup
    charondebug="ike 1, knl 1, cfg 0"
    uniqueids=no

conn ikev2-vpn
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    fragmentation=yes
    forceencaps=yes
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%any
    leftid=@server_domain_or_IP
    leftcert=server-cert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-mschapv2
    rightsourceip=10.10.10.0/24
    rightdns=8.8.8.8,8.8.4.4
    rightsendcert=never
    eap_identity=%identity

Save and close the file once you’ve verified that you’ve configured things as shown.

Now that we’ve configured the VPN parameters, let’s move on to creating an account so our users can connect to the server.

Step 5 Configuring VPN Authentication

Our VPN server is now configured to accept client connections, but we don’t have any credentials configured yet. We’ll need to configure a couple things in a special configuration file called ipsec.secrets:

  • We need to tell StrongSwan where to find the private key for our server certificate, so the server will be able to authenticate to clients.
  • We also need to set up a list of users that will be allowed to connect to the VPN.

Let’s open the secrets file for editing:

$ sudo vim /etc/ipsec.secrets

First, we’ll tell StrongSwan where to find our private key,Then, we’ll define the user credentials. You can make up any username or password combination that you like:

: RSA "server-key.pem"
your_username : EAP "your_password"

Save and close the file. Now that we’ve finished working with the VPN parameters, we’ll restart the VPN service so that our configuration is applied:

$ sudo systemctl restart strongswan

Now that the VPN server has been fully configured with both server options and user credentials, it’s time to move on to configuring the most important part: the firewall.

Step 6 Configuring the Firewall & Kernel IP Forwarding

With the StrongSwan configuration complete, we need to configure the firewall to forward and allow VPN traffic through.

If you followed the prerequisite tutorial, you should have a very basic UFW firewall enabled. If you don’t yet have UFW configured, you can create a baseline configuration and enable it by typing:

$ sudo ufw allow OpenSSH
$ sudo ufw enable

Now, add a rule to allow UDP traffic to the standard IPSec ports, 500 and 4500:

$ sudo ufw allow 500,4500/udp

Next, we will open up one of UFW’s configuration files to add a few low-level policies for routing and forwarding IPSec packets. Before we do, we need to find which network interface on our server is used for internet access. We can find that by querying for the interface associated with the default route:

$ ip route | grep default

Your public interface should follow the word “dev”. For example, this result shows the interface named eth0, which is highlighted below:

Output
default via 203.0.113.7 dev eth0 proto static

When you have your public network interface, open the /etc/ufw/before.rules file in your text editor:

$ sudo nano /etc/ufw/before.rules
Near the top of the file (before the *filter line), add the following configuration block:
*nat
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
COMMIT

*mangle
-A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.0/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
COMMIT

*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
. . .

Change each instance of eth0 in the above configuration to match the interface name you found with ip route. The *nat lines create rules so that the firewall can correctly route and manipulate traffic between the VPN clients and the internet. The *mangle line adjusts the maximum packet segment size to prevent potential issues with certain VPN clients.

Next, after the *filter and chain definition lines, add one more block of configuration:

. . .
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]

-A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 10.10.10.0/24 -j ACCEPT
-A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 10.10.10.0/24 -j ACCEPT

These lines tell the firewall to forward ESP (Encapsulating Security Payload) traffic so the VPN clients will be able to connect. ESP provides additional security for our VPN packets as they’re traversing untrusted networks.

When you’re finished, save and close the file.

Before we restart the firewall, we’ll change some network kernel parameters to allow routing from one interface to another. Open UFW’s kernel parameters configuration file:

$ sudo nano /etc/ufw/sysctl.conf

We’ll need to configure a few things here:

  • First, we’ll enable IPv4 packet forwarding.
  • We’ll disable Path MTU discovery to prevent packet fragmentation problems.
  • We also won’t accept ICMP redirects nor send ICMP redirects to prevent man-in-the-middle attacks.

The changes you need to make to the file are highlighted in the following code:

. . .

# Enable forwarding
# Uncomment the following line
net/ipv4/ip_forward=1

. . .

# Do not accept ICMP redirects (prevent MITM attacks)
# Ensure the following line is set
net/ipv4/conf/all/accept_redirects=0

# Do not send ICMP redirects (we are not a router)
# Add the following lines
net/ipv4/conf/all/send_redirects=0
net/ipv4/ip_no_pmtu_disc=1

Save the file when you are finished. UFW will apply these changes the next time it starts.

Now, we can enable all of our changes by disabling and re-enabling the firewall:

$ sudo ufw disable
$ sudo ufw enable

You’ll be prompted to confirm the process. Type Y to enable UFW again with the new settings.

Reboot server to make it active.

Step 7 Testing the VPN Connection on iOS, and macOS

Now that you have everything set up, it’s time to try it out. First, you’ll need to copy the CA certificate you created and install it on your client device(s) that will connect to the VPN. The easiest way to do this is to log into your server and output the contents of the certificate file:

$ cat /etc/ipsec.d/cacerts/ca-cert.pem

You’ll see output similar to this:

-----BEGIN CERTIFICATE-----
MIIFQjCCAyqgAwIBAgIIFkQGvkH4ej0wDQYJKoZIhvcNAQEMBQAwPzELMAkGA1UE

. . .

EwbVLOXcNduWK2TPbk/+82GRMtjftran6hKbpKGghBVDPVFGFT6Z0OfubpkQ9RsQ
BayqOb/Q
-----END CERTIFICATE-----

Copy this output to your computer, including the —–BEGIN CERTIFICATE—– and —–END CERTIFICATE—– lines, and save it to a file with a recognizable name, such as ca-cert.pem. Ensure the file you create has the .pem extension.

Alternatively, use SFTP to transfer the file to your computer.

Once you have the ca-cert.pem file downloaded to your computer, you can set up the connection to the VPN.

Connecting from iOS

To configure the VPN connection on an iOS device, follow these steps:

  1. Send yourself an email with the root certificate attached.
  2. Open the email on your iOS device and tap on the attached certificate file, then tap Install and enter your passcode. Once it installs, tap Done.
  3. Go to SettingsGeneralVPN and tap Add VPN Configuration. This will bring up the VPN connection configuration screen.
  4. Tap on Type and select IKEv2.
  5. In the Description field, enter a short name for the VPN connection. This could be anything you like.
  6. In the Server and Remote ID field, enter the server’s domain name or IP address. The Local ID field can be left blank.
  7. Enter your username and password in the Authentication section, then tap Done.
  8. Select the VPN connection that you just created, tap the switch on the top of the page, and you’ll be connected.

Connecting from macOS

Follow these steps to import the certificate:

  1. Double-click the certificate file. Keychain Access will pop up with a dialog that says “Keychain Access is trying to modify the system keychain. Enter your password to allow this.”
  2. Enter your password, then click on Modify Keychain
  3. Double-click the newly imported VPN certificate. This brings up a small properties window where you can specify the trust levels. Set IP Security (IPSec) to Always Trust and you’ll be prompted for your password again. This setting saves automatically after entering the password.

Now that the certificate is important and trusted, configure the VPN connection with these steps:

  1. Go to System Preferences and choose Network.
  2. Click on the small “plus” button on the lower-left of the list of networks.
  3. In the popup that appears, Set Interface to VPN, set the VPN Type to IKEv2, and give the connection a name.
  4. In the Server and Remote ID field, enter the server’s domain name or IP address. Leave the Local IDblank.
  5. Click on Authentication Settings, select Username, and enter your username and password you configured for your VPN user. Then click OK.

Finally, click on Connect to connect to the VPN. You should now be connected to the VPN.

Link: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-ikev2-vpn-server-with-strongswan-on-ubuntu-18-04-2

搭建一套redis集群用于测试,搭建过程如下

安装redis的ruby插件,用于构建redis集群。

gem install redis

下载最新的redis安装包:
wget http://download.redis.io/releases/redis-4.0.9.tar.gz
编译安装(本次安装目录在/opt/redis目录下):
tar xzf redis-4.0.9.tar.gz
cd redis-4.0.9
make
make PREFIX=/opt/redis install
将构建集群的脚本拷贝至安装目录
cp src/redis-trib.rb /opt/redis/bin/
制作集群配置文件(至少6个节点):
mkdir -p /opt/redis/cluster/{10001,10002,10003,10004,10005,10006}
echo "port {port}" > ./redis-cluster.conf
echo "dir /opt/redis/cluster/{port}" >> ./redis-cluster.conf
echo "cluster-enabled yes" >> ./redis-cluster.conf
echo "daemonize yes" >> ./redis-cluster.conf
echo "bind 127.0.0.1" >> ./redis-cluster.conf
sed 's/{port}/10001/' ./redis-cluster.conf > /opt/redis/redis-cluster-10001.conf
sed 's/{port}/10002/' ./redis-cluster.conf > /opt/redis/redis-cluster-10002.conf
sed 's/{port}/10003/' ./redis-cluster.conf > /opt/redis/redis-cluster-10003.conf
sed 's/{port}/10004/' ./redis-cluster.conf > /opt/redis/redis-cluster-10004.conf
sed 's/{port}/10005/' ./redis-cluster.conf > /opt/redis/redis-cluster-10005.conf
sed 's/{port}/10006/' ./redis-cluster.conf > /opt/redis/redis-cluster-10006.conf
启动节点:
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10001.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10002.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10003.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10004.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10005.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10006.conf
关联成集群模式:
echo "yes" | /opt/redis/bin/redis-trib.rb create --replicas 1 127.0.0.1:10001 127.0.0.1:10002 127.0.0.1:10003 127.0.0.1:10004 127.0.0.1:10005 127.0.0.1:10006
集群重启脚本:
PIDS=`ps -ef | grep '/opt/redis/bin/redis-server' | grep '127.0.0.1:1000' | awk '{print $2}'`
for i in $PIDS; do
echo "kill pid $i"
kill $i
done
sleep 3
rm -rf /opt/redis/cluster
mkdir -p /opt/redis/cluster/{10001,10002,10003,10004,10005,10006}
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10001.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10002.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10003.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10004.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10005.conf
/opt/redis/bin/redis-server /opt/redis/redis-cluster-10006.conf
echo "yes" | /opt/redis/bin/redis-trib.rb create --replicas 1 127.0.0.1:10001 127.0.0.1:10002 127.0.0.1:10003 127.0.0.1:10004 127.0.0.1:10005 127.0.0.1:10006
PS: redis集群并没有考虑所有节点同时宕掉的情况,因此没有重启所有集群的命令,此重启脚本将所有数据情况,重建集群,请勿直接使用生产环境,仅限测试开发环境。

在cmake mysql源码的时候出现下面的错误:


[ 46%] Building CXX object sql/CMakeFiles/sql.dir/geometry_rtree.cc.o
c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[2]: *** [sql/CMakeFiles/sql.dir/geometry_rtree.cc.o] Error 4
make[1]: *** [sql/CMakeFiles/sql.dir/all] Error 2
make: *** [all] Error 2   

通过查找,[可能是因为内存不够的原因](https://bitcointalk.org/index.php?topic=304389.0),使用`free -h`查看了下,发现DO的主机连Swap分区都没有,Swap分区是当物理内存不够用的时候,把物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到物理内存中。Swap的调整对Linux服务器,特别是Web服务器的性能至关重要,通过调整Swap,有时可以越过系统性能瓶颈,节省系统升级的费用。   SWAP分区设置多大是我们需要关心的问题,关于设置的规则可以参考下面,实际情况可以根据业务需求进行调整,选择合适的Swap分区大小:

4G以内的物理内存,SWAP 设置为内存的2倍。
4-8G的物理内存,SWAP 等于内存大小。
8-64G 的物理内存,SWAP 设置为8G。
64-256G物理内存,SWAP 设置为16G。   接下来我们看下如何设置Swap分区。 ## 检查是否存在Swap分区   输入`swapon -s`,如果没有任何的信息显示,也就是还没有划分Swap分区。 ## 检查文件系统   如果没有创建Swap分区,再看下硬盘还剩下多少空间可以使用,使用`df`命令查看。因为我先创建了1G的Swap分区,还是报错,于是我选择创建一个2GB大小的Swap分区。 ## 创建Swap分区文件   创建swap文件。

dd if=/dev/zero of=/swapfile bs=2048 count=1M 

该命令将创建一个大小为2GB,文件名为swapfile的Swap分区文件,`of=/swapfile`参数指定了文件的创建位置和文件名;`bs=2048`指定了文件的大小,`count=1M`代表单位。 ## 格式化swap分区


mkswap /swapfile

激活swap分区

swapon /swapfile

查询swap分区

swapon -s 

你会发现在重启之后Swap分区就没了,那是因为上面的设置是一次性的,想要一直启动Swap分区,可以编辑fstab文件。

nano /etc/fstab   在最后一行添加上下面一条:


/swapfile     swap     swap     defaults     0  0   

添加成功后给swap赋予相关权限:

chown root:root /swapfile
chmod 0600 /swapfile ## 配置swappiness   实际上,并不是等所有的物理内存都消耗完毕之后,才去使用swap的空间,什么时候使用是由swappiness 参数值控制。

cat /proc/sys/vm/swappiness   默认值是60,swappiness=0 的时候表示最大限度使用物理内存,然后才是Swap空间;swappiness=100 的时候表示积极的使用Swap分区,并且把内存上的数据及时的搬运到swap空间里面。 ### 临时性修改

sysctl vm.swappiness=10
cat /proc/sys/vm/swappiness   这里我们的修改已经生效,但是如果我们重启了系统,又会变成60。 ### 永久修改   在`/etc/sysctl.conf`文件里添加如下参数:`vm.swappiness=10`,保存重启就可以了。

http://jeremybai.github.io/blog/2015/08/01/centos-creat-swap

搭建了多次vpn服务,从最早的使用pptp到现在的strongswan。从安全角度上来看,strongswan更安全,且目前的设备基本都已支持。关于strongswan更多的信息请参考官方网站

注意:此方法基于Ubuntu版本16.0.4(<= 16.0.4)及以下

部署及安装步骤:

1. 安装strongswan及相关组件

1.1   apt-get install -y strongswan

1.2  apt-get install -y strongswan-plugin-xauth-*

2.  配置strongswan服务

2.1  配置/etc/ipsec.secrets文件

# This file holds shared secrets or RSA private keys for authentication.
# RSA private key for this host, authenticating it to any other host
# which knows the public part.
x.x.x.x %any : PSK "ps-key"
user1 : XAUTH "password1"
user2 : XAUTH "password2"

注:其中x.x.x.x你服务器的公网IP地址;ps-key为共享密码;user1,user2分别为vpn登陆用户名;password1,password2分别为vpn登陆密码;以上信息请修改为你想设置的用户名及密码即可。

       2.2  配置/etc/ipsec.conf文件

# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
    cachecrls=yes
    uniqueids=yes

conn ios
    keyexchange=ikev1
    authby=xauthpsk
    xauth=server
    left=%defaultroute
    leftsubnet=0.0.0.0/0
    leftfirewall=yes
    right=%any
    rightsubnet=192.168.5.0/24
    rightsourceip=192.168.5.1/24
    rightdns=8.8.8.8
    auto=add

3. 配置网络

3.1 网络转发(iptables)

iptables -t nat -A POSTROUTING -s 192.168.5.0/24 -o eth0 -j MASQUERADE

3.2 将如下命令写入/etc/rc.local

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 8192 > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo 40000 > /proc/sys/net/ipv4/tcp_max_tw_buckets
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

4. 重启服务器即可

PS:如果不方便重启服务器,也可以使用如下命令:

sysctl net.ipv4.ip_forward=1

重启strongswan服务:service strongswan stop  && service strongswan start

背景

当今互联网,数据呈现爆炸式增长,社交网络、移动通信、网络视频、电子商务等各种应用往往能产生亿级甚至十亿、百亿级的海量小文件。由于在元数据管理、访问性能、存储效率等方面面临巨大的挑战,海量小文件问题成为了业界公认的难题。

业界的一些知名互联网公司,也对海量小文件提出了解决方案,例如:著名的社交网站Facebook,存储了超过600亿张图片,专门推出了Haystack系统,针对海量小图片进行定制优化的存储。

白山云存储CWN-X针对小文件问题,也推出独有的解决方案,我们称之为Haystack_plus。该系统提供高性能数据读写、数据快速恢复、定期重组合并等功能。

Facebook的Haystack

Facebook的Haystack对小文件的解决办法是合并小文件。将小文件数据依次追加到数据文件中,并且生成索引文件,通过索引来查找小文件在数据文件中的offset和size,对文件进行读取。

Haystack的数据文件部分

Haystack的数据文件,将每个小文件封装成一个needle,包含文件的key、size、data等数据信息。所有小文件按写入的先后顺序追加到数据文件中。

Haystack的索引文件部分

Haystack的索引文件保存每个needle的key,以及该needle在数据文件中的offset、size等信息。程序启动时会将索引加载到内存中,在内存中通过查找索引,来定位在数据文件中的偏移量和大小。

Haystack面临的问题

Facebook的Haystack特点是将文件的完整key都加载到内存中,进行文件定位。机器内存足够大的情况下,Facebook完整的8字节key可以全部加载到内存中。

但是现实环境下有两个主要问题:

  1. 存储服务器内存不会太大,一般为32G至64G;
  2. 小文件对应的key大小难控制,一般选择文件内容的MD5或SHA1作为该文件的key。

场景举例

  • 一台存储服务器有12块4T磁盘,内存为32GB左右。
  • 服务器上现需存储大小约为4K的头像、缩略图等文件,约为10亿个。
  • 文件的key使用MD5,加上offset和size字段,平均一个小文件对应的索引信息占用28字节。
  • 在这种情况下,索引占用内存接近30GB,磁盘仅占用4TB。内存消耗近100%,磁盘消耗只有8%。

所以索引优化是一个必须要解决的问题。

Haystack_plus

Haystack_plus的核心也由数据文件和索引文件组成。

1. Haystack_plus的数据文件

与Facebook的Haystack类似,Haystack_plus将多个小文件写入到一个数据文件中,每个needle保存key、size、data等信息。

2. Haystack_plus的索引文件

索引是我们主要优化的方向:

  • 索引文件只保存key的前四字节,而非完整的key;
  • 索引文件中的offset和size字段,通过512字节对齐,节省1个字节;并根据整个Haystack_plus数据文件实际大小计算offset和size使用的字节数。

3. Haystack_plus的不同之处

数据文件中的needle按照key的字母顺序存放。

由于索引文件的key,只保存前四字节,如果小文件key的前四字节相同,不顺序存放,就无法找到key的具体位置。可能出现如下情况:

例如:用户读取的文件key是0x ab cd ef ac ee,但由于索引文件中的key只保存前四字节,只能匹配0x ab cd ef ac这个前缀,此时无法定位到具体要读取的offset。

我们可以通过needle顺序存放,来解决这个问题:

例如:用户读取文件的key是0x ab cd ef ac bb,匹配到0x ab cd ef ac这个前缀,此时offset指向0x ab cd ef ac aa这个needle,第一次匹配未命中。

通过存放在needle header中的size,我们可以定位0x ab cd ef ac bb位置,匹配到正确needle,并将数据读取给用户。

4. 索引搜索流程为

5. 请求不存在的文件

问题:我们应用折半查找算法在内存查找key,时间复杂度为O(log(n)),其中n为needle数目。索引前缀相同时,需要在数据文件中继续查找。此时访问的文件不存在时,容易造成多次IO查找。

解决方法:在内存中,将存在的文件映射到bloom filter中。此时只需要通过快速搜索,就可以排除不存在的文件。

时间复杂度为O(k),k为一个元素需要的bit位数。当k为9.6时,误报率为1%,如果k再增加4.8,误报率将降低为0.1%。

6. 前缀压缩,效果如何

Haystack_plus与Facebook Haystack内存消耗的对比,场景举例,文件(如:头像、缩略图等)大小4K,key为MD5:

内存消耗对比

Key

offset

size

Haystack

全量key,16字节

8字节

4字节

Haystack_plus

4字节

4字节

1字节

注:Haystack的needle为追加写入,因此offset和size大小固定。Haystack_plus的key使用其前4字节,offset根据Haystack_plus数据文件的地址空间计算字节数,并按512字节对齐;size根据实际文件的大小计算字节数,并按512对齐。

从上图可以看出在文件数量为10亿的情况下,使用Facabook的Haystack消耗的内存超过26G,使用Haystack_plus仅消耗9G多内存,内存使用降低了2/3。

7.索引优化根本就停不下来

10亿个4K小文件,消耗内存超过9G。Key占用4字节,Offset占用4字节,还需要再小一些。

索引分层

根据文件key的前缀,进行分层,相同的前缀为一层。

分层的好处

减少key的字节数

通过分层,只保存一份重复的前缀,节省key的字节数。

减少offset的字节数

优化前的offset,偏移范围为整个Haystack_plus的数据文件的地址空间。

优化后,只需在数据文件中的层内进行偏移,根据最大的层地址空间可以计算所需字节数。

分层后的效果

从上图可以看出,进行分层后,内存消耗从优化前的9G多,降低到4G多,节省了一半的内存消耗。

Haystack_plus整体架构

1. Haystack_plus组织

每台服务器上,我们将所有文件分成多个group,每个group创建一个Haystack_plus。系统对所有的Haystack_plus进行统一管理。

读、写、删除等操作,都会在系统中定位操作某个Haystack_plus,然后通过索引定位具体的needle,进行操作。

2. 索引组织

之前已经介绍过,所有needle顺序存放,索引做前缀压缩,并分层。

3. 文件组成

  • chunk文件:小文件的实际数据被拆分保存在固定数量的chunk数据文件中,默认为12个数据块;
  • needle list文件:保存每个needle的信息(如文件名、offset等);
  • needle index和layer index文件:保存needle list在内存中的索引信息;
  • global version文件:保存版本信息,创建新version时自动将新版本信息追加到该文件中;
  • attribute文件:保存系统的属性信息(如chunk的SHA1等);
  • original filenames:保存所有文件原始文件名。

A、Haystack_plus数据文件被拆分为多个chunk组织,chunk1,chunk2,chunk3……

B、分成多个chunk的好处:

1. 数据损坏时,不影响其它chunk的数据;

2. 数据恢复时,只需恢复损坏的chunk。

C、每个chunk的SHA1值存放在attribute文件中。

4. 版本控制

由于needle在数据文件中按key有序存放,为不影响其顺序,新上传的文件无法加入Haystack_plus,而是首先被保存到hash目录下,再通过定期自动合并方式,将新文件加入到Haystack_plus中。

合并时将从needle_list文件中读取所有needle信息,将删除的needle剔除,并加入新上传的文件,同时重新排序,生成chunk数据文件、索引文件等。

重新合并时将生成一个新版本Haystack_plus。版本名称是所有用户的文件名排序的SHA1值的前4字节。

每半个月系统自动进行一次hash目录检查,查看是否有新文件,并计算下所有文件名集合的SHA1,查看与当前版本号是否相同,不同时说明有新文件上传,系统将重新合并生成新的数据文件。

同时,系统允许在hash目录下超过指定的文件数时,再重新创建新版本,从而减少重新合并次数。

版本的控制记录在global_version文件中,每次创建一个新版本,版本号和对应的crc32将追加到global_version文件(crc32用于查看版本号是否损坏)。

每次生成新版本时,自动通知程序重新载入索引文件、attribute文件等。

5. 数据恢复

用户的文件将保存成三副本存放,因此Haystack_plus也会存放在3台不同的机器上。

恢复场景一

当一个Haystack_plus的文件损坏时,会在副本机器上,查找是否有相同版本的Haystack_plus,如果版本相同,说明文件的内容都是一致,此时只需将要恢复的文件从副本机器下载下来,进行替换。

恢复场景二

如果副本机器没有相同版本的Haystack_plus,但存在更高版本,那此时可以将该版本的整个Haystack_plus从副本机器上拷贝下来,进行替换。

恢复场景三

如果前两种情况都不匹配,那就从另外两台副本机器上,将所有文件都读到本地上的hash目录下,并将未损坏的chunk中保存的文件也提取到hash目录下,用所有文件重新生成新版本的Haystack_plus。

Haystack_plus效果如何

在使用Haystack_plus后一段时间,我们发现小文件的整体性能有显著提高,RPS提升一倍多,机器的IO使用率减少了将近一倍。同时,因为优化了最小存储单元,碎片降低80%。

使用该系统我们可以为用户提供更快速地读写服务,并且节省了集群的资源消耗。

Link: http://www.infoq.com/cn/articles/solution-of-massive-small-files

由于Jenkins的日志文件很快就被写满了系统磁盘空间,导致很多系统故障。查看了一下日志文件,是由于dns解析异常导致的Jenkins日志爆涨。

首先停掉Jenkins服务,清理掉日志文件,日志文件默认路径/var/log/jenkins/jenkins.log。

为了避免类似问题,关掉此类日志文件。

操作如下:

系统管理-> System Log->日志级别(在左边栏)

添加

Name: javax.jmdns

Level: off

点击提交即可关闭此类日志。