Windows 7 & Arch Linux U盘安装二合一

距离上次发文也一年多了, 真是时光飞逝. 这一年工作接触了很多也做了很多, 不过其实学得越多越发现自己是小白, 也不好意思写文章误导大众了><, 分享一些小经验吧.

话说最近转战Arch Linux, 不过U盘已经放了个Windows 7, 就想弄个双启动. 双启动就得给U盘重新装个引导呗, 不过折腾了半天syslinux没搞定, 启动时卡在那黑屏, 也没啥报错信息. 还是上GRUB吧. 以下是在U盘上安装GRUB并配置双启动的方法.

U盘的目录结构

由于我的U盘之前做成了Windows 7的安装盘, 所以弄成了如下的文件结构. 直接引导Windows 7的ISO谁有兴趣的话也可以尝试下.

  • Windows 7: 直接解压镜像至U盘根目录.
  • Arch Linux: 直接把ISO放于U盘/boot/isos/下.

GRUB的安装

在Ubuntu下直接用grub-install即可, 其它系统可查阅相关文档.

grub-install --boot-directory=/mnt/usb/boot /dev/sdb


其中/dev/sdb是U盘设备, 假设U盘被挂载到/mnt/usb目录下.

GRUB的配置

以下是grub.cfg, 在U盘的/boot/grub/下, 注意不要和你硬盘的/boot搞混了!

set timeout=10
set default=0

menuentry "Arch" {
 set isofile="/boot/isos/archlinux-2013.09.01-dual.iso"
 loopback loop /$isofile
 linux (loop)/arch/boot/x86_64/vmlinuz archisolabel=ARCH_201309 img_dev=/dev/disk/by-label/GSP1RMCULXF img_loop=$isofile earlymodules=loop
 initrd (loop)/arch/boot/x86_64/archiso.img
}

menuentry "Windows 7" {
 insmod part_msdos
 insmod ntfs
 insmod ntldr
 ntldr /bootmgr
}

其中Arch的引导需要指定下镜像文件所在设备的路径img_dev, 我这边是根据U盘的Label(img_dev=/dev/disk/by-label/GSP1RMCULXF)找的, 不知道有没有更好的办法.

至此从U盘启动的时候就会出现启动菜单, 当然也可以类似地加入Ubuntu等, 不过要注意的是其它发行版和Arch的ISO目录结构可能不太一样, 需要查阅下相关文档看怎么配置引导.

完结撒花><!


2014.04.16 Update

贴一个Ubuntu的配置:

menuentry "Ubuntu 13.10 Desktop amd64" {
 set isofile="/boot/isos/ubuntu-13.10-desktop-amd64.iso"
 loopback loop /$isofile
 linux (loop)/casper/vmlinuz.efi boot=casper img_dev=/dev/disk/by-label/GSP1RMCULXF iso-scan/filename=$isofile noprompt noeject
 initrd (loop)/casper/initrd.lz
}
Advertisements

Cisco IPSec VPN For Debian

最近倒腾了下OpenVPN, 发现虽然用起来比SSH速度快点但拨上去实在是太慢. 看到推上的巨巨们都在上Cisco IPSec, 索性决定也自己上一个. 倒腾了下发现配置也不是很复杂, 网上也有巨巨们十分详细的配置步骤, 只是自己在配的过程中也发现有几个地方需要特别注意下, 在此流水帐下吧.

服务端


racoon

服务端配置主要是racoon, 配置文件参考了这篇文章这篇文章, 在此非常感谢. 另外这篇关于如何兼容黑莓的文章讲得也非常清楚, 再次一并推荐下.

既然是Debian安装当然是apt-get:

apt-get install racoon

然后是几个配置文件:

# /etc/racoon/racoon.conf

path pre_shared_key “/etc/racoon/psk.txt”;
path certificate “/etc/racoon/certs”;

listen {
    isakmp SERVER.IP.ADDRESS [500];
    isakmp_natt SERVER.IP.ADDRESS [4500];
}
 
remote anonymous {
    exchange_mode aggressive, main, base;
    mode_cfg on;
    proposal_check obey;
    nat_traversal on;
    generate_policy unique;
    ike_frag on;
    passive on;
    dpd_delay 30;
     
    proposal {
        lifetime time 28800 sec;
        encryption_algorithm 3des;
        hash_algorithm md5;
        authentication_method xauth_psk_server;
        dh_group 2;
    }
}
 
sainfo anonymous {
    encryption_algorithm aes, 3des, blowfish;
    authentication_algorithm hmac_sha1, hmac_md5;
    compression_algorithm deflate;
}
 
mode_cfg {
    auth_source system;
    dns4 8.8.8.8;
    banner “/etc/racoon/motd”;
    save_passwd on;
    network4 10.12.0.100;
    netmask4 255.255.255.0;
    pool_size 100;
    pfs_group 2;
}

# /etc/racoon/psk.txt

# Group Name Group Secret
GROUP.NAME GROUP.SECRET

设置好psk.txt的权限:

chmod 600 /etc/racoon/psk.txt

# /etc/racoon/motd

# Banner
Welcome to Cisco IPSec!

Account

用户验证用的是系统的用户系统, 简单的新建一个用户即可, 为了安全性shell可设为/bin/false.

useradd -MN -b /tmp -s /bin/false USER
passwd USER

iptables

添加以下规则以开放相应端口和NAT转发.

iptables -A INPUT -p udp -–dport 500 -j ACCEPT
iptables -A INPUT -p udp –dport 4500 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.12.0.0/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -s 10.12.0.0/24 -j ACCEPT

重启服务器后以上规则将失效, 持久化参见这篇文章.

ipv4 forward

# /etc/sysctl.conf

net.ipv4.ip_forward=1

修改后使用如下命令使之生效:

sysctl -p /etc/sysctl.conf

客户端


Linux

Linux可以使用vpnc作为客户端, 配置文件如下:

# /etc/vpnc/default.conf

IPSec gateway SERVER.DOMAIN/IP
IPSec ID GROUP.NAME
IPSec secret GROUP.SECRET
IKE Authmode psk
Xauth username USER.NAME
Xauth password USER.PASSWORD
NAT Traversal Mode cisco-udp

之后可以使用vpnc-connect/vpnc-disconnect连接和断开VPN.

Dnsmasq设置简介

说是简介其实也不想详细介绍, 具体官网上都有, 一搜便知. 这里只是简单地罗列下常用配置, 以供参考.

#不读取/etc/resolv.conf文件
no-resolv

#不扫描/etc/resolv.conf和/etc/dnsmasq.conf文件的改动,如果有改动直接重启程序即可
no-poll

#设置dns服务器
server=8.8.8.8

#指定*.domain.name用8.8.8.8解析
server=/domain.name/8.8.8.8
注意不是server=/*.domain.name/8.8.8.8

#解析*.domain.name到127.0.0.1
address=/domain.name/127.0.0.1

#无效的DNS服务器, 用于反DNS劫持
bogus-nxdomain=127.0.0.1

下列一个典型的配置文件, 用于tomato, 要使其生效请开启截获DNS端口.

#覆盖掉原有DNS设置
no-resolv

#对baidu.com及其子域名使用中国电信的DNS
server=/baidu.com/218.2.135.1

#对其它的域名使用Google DNS
server=8.8.8.8

C#控制台输出实时重定向

.Net Framework中的Process类和ProcessStartInfo类可以方便地控制进程的启动, 还可以方便地将控制台程序的输出重定向到Stream中, 然后显示到TextBox中或者记录到文件中. 不过要实时显示每一行的输出还得用点技巧, 方法如下.

启动进程前的准备.

//设置待启动程序的路径和要传递的参数
ProcessStartInfo info = new ProcessStartInfo(path, args));

//将标准输出流重定向, 需同时把UseShellExecute设置为false
info.RedirectStandardOutput = true;

//不使用操作系统外壳程序启动
info.UseShellExecute = false;

//不创建窗体
info.CreateNoWindow = true;

为了做到实时捕获, 需在进程结束前一直搜索输出流, 如有新的一行便读取并引发一个事件以让主程序窗体能够响应并将这行添加至TextBox.

if (process.Start())
{
    while (!process.HasExited)
    {
        string line = process.StandardOutput.ReadLine();
        if (line != null)
            OutputLineGet(line);
    }
    process.WaitForExit();
}

为了不让窗体假死, 将调用上述循环放至另一个的单独线程中.

public void Start()
{
    new System.Threading.Thread(new System.Threading.ThreadStart(this.StartConsoleProgram)).Start();
}


然后便是窗体响应该事件, 注意到是跨线程调用GUI, 需用委托.

public MainForm()
{
  InitializeComponent();

  //注册事件
  this.OutputLineGet += new OnOutputLineGetDelegate(MainForm_OutputLineGet);
}

public delegate void OnOutputLineGetDelegate(string line);
public event OnOutputLineGetDelegate OutputLineGet;

private void MainForm_OutputLineGet(string line)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new OnOutputLineGetDelegate(MainForm_OutputLineGet), line);
    }
    else
    {
        txtLog.AppendText(line);

        //添加换行符
        txtLog.AppendText("rn");
    }
}

这样便能一行一行实时捕获输出了, 而且主程序也可以响应窗体消息不至于假死.

jQuery实现滑动效果

最近网上似乎开始流行滑动效果, 比如说M$主页上的这个. 虽然M$的这个是为了配合Metro的主题, 但是滑动展示却确实广泛应用于各大网站的主页上. 网上实现滑动效果的js插件一抓一大把, 但是既然我们用了jQuery做Ajax, 何不想想jQuery框架内就能解决的方案.

解决大体思路是: 在一个wrapper div里放N个等大的sub div, 并列放置, 多余部分不显示, 滑动时改变各个sub div的水平位置即可实现slide. 当然为了做成"滑动", 要用到jQuery的.animate()方法(当然别的框架也可以).

并列放置一般来说是把每个sub div的float设成left, 不过float其实并不是并列排版的最佳方案, 因为sub div从wrapper中"浮"了出来不再属于wrapper, 造成wrapper包不住sub. 需在某处应用clear, 典型的方法是新建个空div应用clear: both. 这样做未免有点Hack的味道, 空的div也不容易理解.

另一个方法是将每个sub div的position设成relative, 然后将后一个的top设成-300px(如每个sub div高度为300px). 这里的top是相对于前一个div而言的, 所以后面第二个的top应设为-600px. 关于relative的排版参见这里.

CSS3中对于元素并列放置有更好的解决方案: display: inline-block. 允许像div这种块级元素拥有inline的特性. 强烈建议对于块级元素的并列排放使用inline-block而不是float.

我用了第二种方法(虽然事实上第三种方法更好), 不过怎么排版其实并不重要, 排成一排就行了.

对于wrapper, 用overflow: hidden隐藏多余的sub div.

向左滑动时, 在js中对所有sub div调用.animate({"left", "-=300px"}).
向右滑动时, 在js中对所有sub div调用.animate({"left", "+=300px"}).

未防滑过头, 滑动之前需判断是否已到底.

其它方法可能调用.animate()时渐变的属性略有不同, 相应调整即可. 不过.animate()可调的属性限于几个可以连续变化的数值属性, 具体可参阅jQuery的文档.

简言之, 选择一个合适的方法并列排版sub div, 遮掉多余部分, 滑动时左右调整位置, 就这么简单.

附: Source Code

nginx泛二级域名配置

nginx有着非常强大的rewrite功能, 结合正则表达式可以定义非常灵活的泛二级域名.

假设/home/www中分别有company1/和company2/两个网站, 希望分别有各自的二级域名.

在nginx配置文件中使用如下语句即可分离出二级域名, 保存至变量$subdomain, 默认为company1.

set $subdomain company1;
if ( $http_host ~* "^(.*).archangelsdy.com$") {
    set $subdomain $1;
}

之后用root语句定位至对应的主目录.

root /home/www/$subdomain;

同样, fastcgi的转发也相应修改为:

fastcgi_param  SCRIPT_FILENAME  /home/www/$subdomain$fastcgi_script_name;

如上配置后, 对于某个二级域名便可重定向置/home中对应的目录. 显然, 用这种方便配置后, 以后添加二级域名只需要配置好域名解析并在/home中建立相应目录即可, 不需要修改nginx的配置文件也不需要重启nginx, 可批量添加二级域名三级域名等, 缺点是对于每个二级域名下的网站配置都是相同的.