在 Raspberry Pi 2 上安装 Hardened Gentoo

一段时间以前入了树梅派,想当作日后的主力服务器使用,尝试配置一个好用的服务器,而且最近比较热衷于 hardened 系统,可以提供额外的安全。

配置参考:https://wiki.gentoo.org/wiki/Raspberry_Pi

首先应该配置sd卡分区,我之前用的raspbian,打算直接用旧的分区,不动boot分区,只对root分区(mount在/mnt/ext4上)进行修改。

首先下来最新的stage3,校验,解压:

wget http://distfiles.gentoo.org/experimental/arm/hardened/stage3-armv7a_hardfp-hardened-201xxxxx.tar.bz2

wget http://distfiles.gentoo.org/experimental/arm/hardened/stage3-armv7a_hardfp-hardened-201xxxxx.DIGESTS

和 DIGESTS 对比核对下各种校验值对不对,之后解压到sd卡根目录(/mnt/ext4):

tar xvf stage3-armv7a_hardfp-hardened-201xxxxx.tar.bz2 -C /mnt/ext4/

由于正在PC上使用gentoo,直接使用cp /usr/portage ./usr/ 复制portage tree。注意先清理一下distfiles。

cp /usr/portage /mnt/ext4/usr/portage -r

如果没有现成的Portage Tree下载解压一个即可。

 

Linux Kernel and Grsecurity Patch:

配置Toolchain:

Gentoo 中可以很方便地使用 crossdev 配置:

crossdev -S -v -t armv7a-hardfloat-linux-gnueabi

或者其他方式准备工具链,之后设置环境变量:

export ARCH=arm

export CROSS_COMPILE=armv7a-hardfloat-linux-gnueabi-

export INSTALL_MOD_PATH=/mnt/ext4

export INSTALL_HDR_PATH=/mnt/ext4

export KERNEL=kernel7

准备内核代码:

git clone git://github.com/raspberrypi/linux.git

如果已有现成的Linux git repo ,而且不介意加入更多remote的话,可以通过

git remote add rasp git://github.com/raspberrypi/linux.git

git fetch rasp

更快地获得代码。

应用Grsecurity补丁,使用branch rpi-4.3.y的代码。

git checkout rasp/rpi-4.3.y

wget https://grsecurity.net/test/grsecurity-3.1-4.3.3-201xxxxxxxxx.patch

patch -p1 -s < grsecurity-3.1-4.3.3-201xxxxxxxxx.patch

有Reject,一般比较好解决,手动解决即可。

写了个小Patch,修复驱动的小问题:

diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
index 8072ff6..74c3af3 100644
--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
+++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c
@@ -39,8 +39,6 @@

#include "vchiq_util.h"

-#include <stddef.h>
-
#define vchiq_status_to_vchi(status) ((int32_t)status)

typedef struct {
diff --git a/drivers/net/wireless/rtl8192cu/include/hal_intf.h b/drivers/net/wireless/rtl8192cu/include/hal_intf.h
index cac4408..2c08180 100644
--- a/drivers/net/wireless/rtl8192cu/include/hal_intf.h
+++ b/drivers/net/wireless/rtl8192cu/include/hal_intf.h
@@ -231,7 +231,7 @@ struct hal_ops {

s32 (*c2h_handler)(_adapter *padapter, struct c2h_evt_hdr *c2h_evt);
c2h_id_filter c2h_id_filter_ccx;
-};
+} __no_const;

typedef        enum _RT_EEPROM_TYPE{
EEPROM_93C46,
diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_io.h b/drivers/net/wireless/rtl8192cu/include/rtw_io.h
index daf342ac..1ef9295 100644
--- a/drivers/net/wireless/rtl8192cu/include/rtw_io.h
+++ b/drivers/net/wireless/rtl8192cu/include/rtw_io.h
@@ -152,7 +152,7 @@ struct _io_ops
void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
void (*_write_port_cancel)(struct intf_hdl *pintfhdl);

-};
+} __no_const;

准备config,通过menuconfig开关一下Grsecurity的安全选项:

make bcm2709_defconfig

make menuconfig

按需修改,测试发现需要关闭以下Grsecurity相关标记,不然树梅派会不能启动。CONFIG_PAX_KERNEXEC,CONFIG_PAX_MEMORY_UDEREF,CONFIG_GRKERNSEC_RANDSTRUCT

注意:使用CONFIG_DEBUG_RODATA 会让 Grsecurity 的 RBAC 无法开启,开启会导致Kernel Panic。

编译内核,模块,Devtree。

make zImage modules dtbs

安装新内核:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ext4 modules_install

make headers_install

cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img

scripts/mkknlimg arch/arm/boot/zImage mnt/fat32/$KERNEL.img

cp arch/arm/boot/dts/*.dtb mnt/fat32/

cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat32/overlays/

cp arch/arm/boot/dts/overlays/README mnt/fat32/overlays/

sync

sudo umount mnt/fat32

sudo umount mnt/ext4

修改fstab,加上boot挂载点。

塞入SD可以开机了,其余参考Wiki配置即可。

 

相关连接:

树梅派官方内核编译向导:

https://www.raspberrypi.org/documentation/linux/kernel/building.md

Gentoo Wiki相关:

https://wiki.gentoo.org/wiki/Raspberry_Pi/Quick_Install_Guide

https://wiki.gentoo.org/wiki/Raspberry_Pi/Cross_building

已经打好补丁的Patch:

https://github.com/ryncsn/linux

由于GRSEC违反GPL2协议,应该不会再有更新了,默哀。

搭建自配置可用的IPv6网络

为了能有IPv6链接,在重新配置了系统之后又把以前做过的 Radvd 和 使用 HE 提供的 Tunnel Broker 的服务又配置了一遍:

首先要有一个 Hurrican Electric 的 Tunnel Broker 帐号,注册很方便,过程略。

内核要开启Tunnel支持,可见链接中的Wiki。

自用的配置脚本:

由于我用的ADSL拨号网络IP总是变化,所以不能用固定的文件去配置,需要一枚脚本:

https://github.com/ryncsn/he-ipv6-init-script/raw/master/hev6.sh

放到/usr/local/sbin/

wget https://raw.githubusercontent.com/ryncsn/he-ipv6-init-script/master/hev6.sh -O /usr/local/sbin/hev6-init

vim /usr/local/sbin/hev6-init

按照 Tunnel Broker 帐号和申请的 Tunnel 信息配置开头的各种变量,INTERFACE是 Tunnel 经过的的 Interface,需要能接受服务器发来的 6in4 (Protocal 41) 包,且有独立公网地址。ROUTE_INTERFACE是本地需要提供IPv6网络的接口,对我来说就是内网。

 

配置服务:

要让服务自启动。之后写一个服务资源文件:

Gentoo中:

vim /etc/init.d/hev6-init
#!/sbin/runscript
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$

description="Hurrican Electric Tunnel Broker"

command="/usr/local/sbin/hev6-init"

log_file="/var/log/hev6"
depend() {
        need net
        use logger dns
}

start() {
        ebegin "Starting DDNS on ${IFACE}"
        start-stop-daemon --start --background \
        --stdout $log_file --stderr $log_file \
        --exec $command
}

stop() {
        ebegin "Stopping HE v6 tunnel"
        $command clear
        eend $?
}

启用,启动服务。

rc-update add hev6-init default

service hev6-init start

Systemd版:

vim /etc/systemd/system/hev6.service
[Unit]
Description=Hurrican Electric IPv6 Tunnel Broker
After=syslog.target network.target remote-fs.target nss-lookup.target

[Service]
TimeoutSec=0
PIDFile=/run/hev6.pid
ExecStart=/usr/local/sbin/hev6-init
ExecStop=/usr/local/sbin/hev6-init clear
Restart=on-failure


[Install]
WantedBy=multi-user.target
systemctl enable hev6

systemctl start hev6

服务启动之后通过ping6 ipv6.google.com测试,无问题。

 

配置Radvd:

配置radvd,在要提供IPv6服务的接口上开启路由通知:

emerge radvd

vim /etc/radvd.conf

参考配置,酌情修改网段信息等:

interface eth0
{       
        AdvSendAdvert on;
        
        MinRtrAdvInterval 3;
        MaxRtrAdvInterval 10;
        
        AdvDefaultPreference low;               
        AdvHomeAgentFlag off;
        
        prefix 2001:470:ffff:ffff::/64
        {       
                AdvOnLink on;
                AdvAutonomous on;                                                                               
                AdvRouterAddr on;                                                                                       
        };
};

之后配置服务开机自起:

service radvd start

rc-update add radvd default

Gentoo中启动radvd 服务会自动开启ipv6 forwarding。

我的另一机器是 Centos 7,配置时需要手动在/etc/sysctl.con中加入:

net.ipv6.conf.default.forwarding=1
net.ipv6.conf.all.forwarding=1

 

配置ip6tables:

增加TUNNEL Chain,配置类似如下:

-A FORWARD -j TUNNEL

:TUNNEL - [0:0]
-A TUNNEL -s 2001:470:ffff:ffff::/64 -j ACCEPT
-A TUNNEL -d 2001:470:ffff:ffff::/64 -j ACCEPT
-A TUNNEL -s fe80::/10 -j ACCEPT
-A TUNNEL -d fe80::/10 -j ACCEPT
-A TUNNEL -j RETURN

之后在网络上接入其他设备,ping6 ipv6.google.com,测试无问题即可用。

 

相关链接:

Tunnel broker:

http://tunnelbroker.net/

Gentoo Wiki:

https://wiki.gentoo.org/wiki/IPv6_router_guide#Using_radvd

Gentoo + OpenRC 网络配置 PPPoE 双路网络

自家用的电信网络,允许4台客户机同时拨号,其中ADSL路由进行一次拨号提供家人的上网服务,同时使用花生壳的服务。自己的Pi拨号一次,给自己的网站一个地址,使用Dnspod的DDNS。

但默认网络的路由规则会导致所有出站的包都经由同一个默认路由,有两个线路的话其中一条会不可用,为了实现两个多个域名都能使用,要配置双路网络,加一个路由表:

其中ppp0通过eth0进行拨号,eth0为已配置好的局域网。

1、配置PPPoE:

Gentoo 中开启 ppp flag 后,portage 会自动安装需要的包。

在 /etc/portage/make.conf 中加入 ppp flag

USE="... ppp ..."

emergr 自动安装相关依赖包:

emerge --ask --changed-use --deep @world

2、相对的添加路由表

添加一个路由表,所有经由路由器(经由内网IP)的包会被使用新的路由表进行查询。

vim /etc/iproute2/rt_tables

添加:

...
#
# local
#
1       lan.inet

3、配置网络:

编辑 /etc/conf.d/net,添加对应规则,对应情况修改:

主要的是让eth0启动的时候在路由表中添加对应的规则,让对应的包使用新加的路由表。

config_eth0="<static lan ip here> netmask 255.255.255.0"
routes_eth0="default via 192.168.1.1 dev eth0 src <static lan ip here> table lan.inet"
rules_eth0="from <static lan ip here> lookup lan.inet"

dns_servers_eth0="192.168.1.1"

config_ppp0="ppp"
link_ppp0="eth0"
plugins_ppp0="pppoe"
username_ppp0='<username here>'
password_ppp0='<password here>'
pppd_ppp0="
noauth
defaultroute
usepeerdns
holdoff 3
child-timeout 60
lcp-echo-interval 15
lcp-echo-failure 3
noaccomp noccp nobsdcomp nodeflate nopcomp novj novjccomp"

rc_net_ppp0_need="net.eth0"

4、配置启动脚本:

开机自起:

cp /etc/init.d/net.lo /etc/init.d/net.ppp0

rc-update add net.ppp0 default

重启网络/系统,完成。