• 在Windows环境下让 Python CGI 输出二进制文件

    服务器是Windows的,现在的需求是通过一个CGI脚本输出一个pdf(或者是一个图片)。发现出来的文件的大小变大了,然后内容显示不出来或者乱码,估计是\r\n导致的问题。折腾了一下午,找到了答案。现在的代码如下:

    filename = r'D:\example.pdf'  #我这里要输出pdf
    print 'Content-type: application/pdf\n\n'
    
    import msvcrt
    msvcrt.setmode(1, os.O_BINARY)   #使stdout为二进制
    
    pdf_file = open(filename, 'rb')
    data = pdf_file.read()
    pdf_file.close()
    print data

     

  • 在树莓派上使用基于MT7601的无线网卡(如360/百度/腾讯Wifi)

    20150626更新基于 linux kernel 4.0.6 的步骤,建议先看最后更新的部分

    20151205更新,发现在8月13日时,来自4.2的mt7601u驱动被移植到了4.1.5,所以,升级内核到4.1.5或以上,只需要下载  mt7601u.bin 放到 /lib/firmware/ 下就可以了,就是执行下面这条命令。具体来源见 https://github.com/raspberrypi/linux/issues/1090

    sudo wget https://github.com/porjo/mt7601/raw/master/src/mcu/bin/MT7601.bin -O /lib/firmware/mt7601u.bin

    如果内核是4.1.5以上,下文都不需要看了,驱动已经自带,不需要自己编译,只需要补上 /lib/firmware/mt7601u.bin 就可以了。

    否则,看下面的几行来更新系统,再补上 mt7601u.bin ,也就ok了。

    20170107更新,最近把卡格了重新装raspbian系统,是2016-11-25的版本,内核是4.4,发现mt7601u.bin也已经自带,直接插上就用不需要折腾。这个版本的蛋疼之处在于SSH默认关闭,需要在启动分区加上一个名为ssh的文件,才可以开启SSH。

     


     

    首先,更新你的树莓派(避免编译出来版本不对导致不能insert):

    sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get dist-upgrade
    sudo rpi-update

    更新gcc和g++:

    #可能有点问题,先不要更新  20150506
    #sudo apt-get install gcc-4.8 g++-4.8
    
    #sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 20
    #sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 50
    #sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 20
    #sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 50

    到MTK的官网下载驱动并传到树莓派上:http://www.mediatek.com/zh-CN/downloads/mt7601u-usb/

    解压:

    tar xjvf DPO_MT7601U_LinuxSTA_3.0.0.4_20130913.tar.bz2
    cd DPO_MT7601U_LinuxSTA_3.0.0.4_20130913/

    打开 common/rtusb_dev_id.c,在 {USB_DEVICE(0x148f,0×7601)}, /* MT 6370 */  下面加入以下内容:

    {USB_DEVICE(0x148f,0x760b)}, /* 360 Wifi */
    {USB_DEVICE(0x2955,0x1001)}, /* baidu Wifi */
    {USB_DEVICE(0x2a5f,0x1000)}, /* Tencent WiFi */
    {USB_DEVICE(0x2955,0x0001)}, /* XiaoDu Wifi */
    {USB_DEVICE(0x2717,0x4106)}, /* Xiaomi Wifi */

    打开 include/os/rt_linux.h,找到

    int fsuid;
    int fsgid;

    并把它改为

    kuid_t fsuid;
    kgid_t fsgid;

    查看当前内核的版本:

    uname -r

    显示我的版本是3.18.8+ ,所以下载对应的3.18的linux源码,然后解压:

    wget https://github.com/raspberrypi/linux/archive/rpi-3.18.y.tar.gz
    tar xvfz rpi-3.18.y.tar.gz

    取得root权限,将源码移至/usr/src目录:

    sudo su
    mv linux-rpi-3.18.y /usr/src

    建立内核模块库目录的链接:

    ln -s /usr/src/linux-rpi-3.18.y /lib/modules/3.18.8+/build
    cd /lib/modules/3.18.8+/build

    make mrproper 可以看作更加强劲的 make clean 命令,用来清除环境变量,即清除配置文件,一般编译内核前都要运行:

    make mrproper

    将当前正在使用的系统的内核配置生成内核配置信息:

    gzip -dc /proc/config.gz > .config

    生成编译内核所需要的东西:

    make modules_prepare

    获取内核编译时生成的内核模块导出符号文件。因为不是从头编译内核,所以没有,但是编译内核模块需要这个:

    wget https://github.com/raspberrypi/firmware/raw/master/extra/Module.symvers

    再到网卡驱动目录中编译驱动(进入到DPO_MT7601U_LinuxSTA_3.0.0.4_20130913):

    make
    make install
    modprobe mt7601Usta

    如无报错,驱动就安装完成了。

     

    之后是修改/etc/network/interfaces文件,我改成这样:

    auto lo
    
    iface lo inet loopback
    iface eth0 inet dhcp
    
    allow-hotplug wlan0
    iface wlan0 inet manual
    wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
    iface default inet dhcp
    
    allow-hotplug ra0
    iface ra0 inet manual
    wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf

    其中添加的ra0是对应MT7601的,wlan0没有改,插其他无线网卡应该也能正常用。

    然后修改/etc/wpa_supplicant/wpa_supplicant.conf,填入要连接的无线网络的配置。

    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    update_config=1
    
    network={
            ssid="yourssid"
            psk="yourpassword"
            proto=RSN
            key_mgmt=WPA-PSK
            pairwise=CCMP TKIP
            group=CCMP TKIP
            auth_alg=OPEN
            priority=3
    }

    最后的priority是该配置的优先级,数字越大越先连接。添加几个就能在不同的地方自动连接了。

    重启机器,用ifconfig、iwconfig等测试无线网卡能否正常工作。

    20150110215621

    rdp远程登录进去,打开Wifi设置后的截图

     

    =========================

    20150306更新:在内核更新到3.18后,驱动需要重新编译,出现了种种问题,在参考了[2]和[3]后,升级了gcc版本和修改了rt_linux.h。

    20150306于RaspberryPi Model B+测试成功,内核为3.18.8。

    20150506更新:在升级gcc后,似乎在make modules_prepare时会遇到compiler too buggy的问题。我又找了一下,还是在树莓派的官方论坛,https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=49864&start=179这里:

    On the first time running rpi-source, you have to have the default gcc 4.6.3. You have to also specify –skip-gcc so that rpi-source doesn’t care about the different gcc in use and what’s been used to build the default kernel. If you run rpi-source with 4.8.2 as the default gcc, you’ll end up getting message like this during the kernel preparation (make prepare?) phase:

    …error Your compiler is too buggy; it is known to miscompile kernels…

    That’s why you have to first run rpi-source with the default gcc 4.6.3 with –skip-gcc parameter. After rpi-source gets all done, you have to change to gcc 4.8.2. The kernel doesn’t let you compile the kernel itself, but you can compile compatible modules for it. It’s bit tricky . It would be great if the default Raspbian gcc would compile compatible modules. Maybe gcc 4.8.3 would not complain about the kernel miscompile problem?

    似乎是先用自带的4.6.3 prepare好了之后,再换用4.8的意思,各位研究一下吧。

    20150623更新:在https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=49864&start=353找到了一个适用于3.18.11+ #776的驱动,传到了百度盘,使用方法:

    tar xzf mt7601-3.18.11-776.tar.gz
    /install.sh

    另外,在github上有了第三方的驱动,适用于kernel 3.19以上的版本,并且被合并到kernel 4.2,所以未来升级到4.2的时候就再也不用烦恼了。如果要自己编译,就到上面的github链接看看吧。


    20150626更新

    今天把我的RPi B+更新到了4.0.6内核,(Linux raspberrypi 4.0.6+ #798 PREEMPT Tue Jun 23 17:48:03 BST 2015 armv6l),然后成功使用了上文提到的github的新驱动。

    步骤与之前的基本相同。以下步骤未详细说明的都在本文中有提及。

    1. 更新树莓派
    2. 确保使用的是gcc 4.6
    3. 查看当前内核的版本,下载对应的源码,解压,移到/usr/src
    4. 建立内核模块库目录的链接,并切换目录到/lib/modules/`uname -r`/build
    5. make mrproper
    6. sudo modprobe configs   #这会生成 /proc/config.gz
    7. gzip dc /proc/config.gz > .config
    8. make modules_prepare
    9. 下载Module.symvers
    10. 切换到gcc 4.8,(就是前文update-alternatives的那几行)不然编译出来会kernel oops,我试过了,20150506的更新也有提到这一点
    11. https://github.com/porjo/mt7601或官方驱动中的src/mcu/bin/MT7601.bin复制到/lib/firmware/下,命名为mt7601u.bin
    12. 下载驱动源码 https://github.com/kuba-moo/mt7601u/archive/master.zip 并解压到你喜欢的目录,在usb.c里自带了很多USB DEV ID,包括360腾讯小米等,应该不用自己添加了
    13. make && sudo make install && sudo depmod
    14. sudo modprobe mt7601u(make install 之后mt7601u.ko会放到/lib/modules/4.0.6中,如果有问题就放到/lib/modules/4.0.6+/kernel/drivers/net/wireless/下吧)
    15. 插上你的MT7601,ifconfig看一下有没有wlan0吧
    16. /etc/network/interfaces文件中没有ra0部分,只用wlan0

     

     

    相关参考:

    1.在树莓派上使用360WIFI(也适用于小米、百度、腾讯WIFI):http://shumeipai.nxez.com/2014/12/07/raspberry-pi-use-360wifi.html

    2.http://www.raspberrypi.org/forums/viewtopic.php?f=28&t=98913

    3.http://www.raspberrypi.org/forums/viewtopic.php?f=28&t=49864&p=690479

  • OpenWrt使用无线网络桥接LAN与WAN

    先上图。最近我正要搭建一个类似上图的网络,我要从图中的LAN Host 1通过wifi访问图中的WLAN Client,其中两个无线路由器都运行OpenWrt。后来我找到了这篇文章。从中发现了来自OpenWrt Wiki的方法(上图也是取自此wiki),正好解决了这个问题。

  • Openwrt上通过ddns-scripts实现dnspod域名的基于ipv6的ddns

    上一篇文章中,我们通过ddns-scripts和一个外部的.php文件,实现了dnspod上的ipv4的ddns功能。

    最近有了ipv6的ddns的需求,于是在上文的基础上小改了一下,现在dnspod上的ipv6的ddns也没问题了。

     

    How?

    1.在上一篇文章的基础上,修改了一下dnspodupdate.php中的“’record_type’=>’A”为“’record_type’=>’AAAA’”,也可以直接下载:dnspodupdate6.zip,并上传到一个外网的空间上。

    2.修改路由器里的/usr/lib/ddns/dynamic_dns_functions.sh,把位于约75行的

    current_ip=$(ifconfig $ip_interface | grep -o 'inet addr:[0-9.]*' | grep -o "$ip_regex")
    

    改为

    current_ip=$(ifconfig $ip_interface | grep 'Global' | grep -o 'addr: [0-9a-f:]*' | cut -c7-)
    #我的grep和cut是现学现卖的,有没有更好的写法?
    

    不过这样一来,以“接口”来获取ip的就只能获取ipv6的地址了,如果要获取ipv4的地址,“”就选“网络”吧。

    3.打开/usr/lib/ddns/services,添加一行

    "dnspod.com_ipv6" "http://www.xxxxx.com/api/dnspodupdate6.php?username=[USERNAME]&password=[PASSWORD]&domain=[DOMAIN]&myip=[IP]"
    #注意这里的http://www.xxxxx.com/要改
    

    4.更改/etc/config/ddns的配置,service_name选dnspod.com_ipv6,再填上各种参数,这样就完成了~

  • 在Openwrt上搭建ipv6的OpenVPN服务器

    服务器端的配置

    安装OpenVPN软件

    opkg update
    opkg install openvpn openvpn-easy-rsa  #easy-rsa不一定要安装,我把easy-rsa的操作在PC上进行
    

     

    [important]下面的操作在Windows上进行,请先下载并安装Windows版的OpenVPN。如果你打算在路由上使用easy-rsa,对应的操作见文末参考来源的[/important]

    生成CA和各种证书

    修改 OpenVPN\easy-rsa\vars.bat.sample 为你的信息:

    set KEY_COUNTRY=CN
    set KEY_PROVINCE=Guangdong
    set KEY_CITY=Guangzhou
    set KEY_ORG=7forz
    set KEY_EMAIL=7f@7forz.com
    set KEY_CN=7forz
    set KEY_NAME=7forz
    set KEY_OU=7forz
    set PKCS11_MODULE_PATH=7forz.com
    set PKCS11_PIN=1234

     

    打开cmd,进入 OpenVPN\easy-rsa,运行以下命令:

    init-config

    vars

    clean-all

    build-ca (创建根证书)
    Country Name (2 letter code) [CN]:
    State or Province Name (full name) [Guangdong]:
    Locality Name (eg, city) [Guangzhou]:
    Organization Name (eg, company) [7forz]:
    Organizational Unit Name (eg, section) [7forz]:
    Common Name (eg, your name or your server’s hostname) [7forz]:
    Name [7forz]:
    Email Address [7f@7forz.com]:

    build-dh

    build-key-server server (服务器证书,server为机器名)
    Country Name (2 letter code) [CN]:
    State or Province Name (full name) [Guangdong]:
    Locality Name (eg, city) [Guangzhou]:
    Organization Name (eg, company) [7forz]:
    Organizational Unit Name (eg, section) [7forz]:
    Common Name (eg, your name or your server’s hostname) [7forz]:
    Name [7forz]:
    Email Address [7f@7forz.com]:
    Please enter the following ‘extra’ attributes
    to be sent with your certificate request
    A challenge password []:password
    An optional company name []:

    build-key client1 (创建客户端证书,client1为用户名,之后还可以创建client2,client3)
    Country Name (2 letter code) [CN]:
    State or Province Name (full name) [Guangdong]:
    Locality Name (eg, city) [Guangzhou]:
    Organization Name (eg, company) [7forz]:
    Organizational Unit Name (eg, section) [7forz]:
    Common Name (eg, your name or your server’s hostname) [7forz]:
    Name [7forz]:
    Email Address [7f@7forz.com]:
    Please enter the following ‘extra’ attributes
    to be sent with your certificate request
    A challenge password []:password
    An optional company name []:

    如果出现
    failed to update database
    TXT_DB error number 2
    错误,貌似是因为Common Name相同而导致的,请在生成时修改之或者打开keys\index.txt并清除其中内容,再执行一次build-key client1命令

    之后把 ca.crt  server.*  dh*.pem  传到路由的 /etc/openvpn 目录下

    再把 ca.crt client*.* 放到你电脑的 OpenVPN\config 目录下

    阅读更多…

  • CPU性能天梯图

    转自百度AMD吧,顺便也给自己mark一个。点击查看大图。

  • 【多图】TP-Link TL-WR710N 改8M Flash 刷OpenWrt

    一年多之前为了旅游买了个WR710N,在外还挺好用,回家就放一边了。后来接触到了OpenWrt,发现它Flash太小不能刷,才知道TP缩水得如此严重,显然已经跟不上当前路由器智能化的大潮了…

    好了前面的都是废话,要刷OpenWrt,就要至少4M的Flash,原装16M的RAM其实也是捉襟见肘,但是我的目前水平还不够换RAM,所以先把flash换了再说吧~  o(* ̄▽ ̄*)o

    我找遍全网都没找到几篇详细讲710N改装的文章,尤其是照片很少,于是决定自己写一篇吧,顺便发多几张图。感谢这个帖子给了我不小的帮助。

    阅读更多…

  • OpenWrt通过ddns-scripts使用dnspod的动态域名解析(ddns)功能

    最近想实现在openwrt上的ddns功能,百度google找来找去,多数都是用一个bash脚本来实现的。无奈都要求安装curl或者是wget,其依赖包libopenssl体积庞大,本人路由4M的小ROM实在装不起。

    终于,我找到了http://blog.biner.me/article/OpenWrt-use-dnspod-Dynamic-DNS-ddns.html此文,轻松解决了本问题。

    步骤很简单:

    1. 注册dnspod;
    2. 首先你得要有一个顶级域名,没有的话可以去申请个免费的(例如.tk后缀什么的);
    3. 然后你要有一个支持php的空间,实在没有可以用上文提到的博主提供的接口地址(当然也可以用我提供的,只需把下文的xxx改为7forz即可);
    4. 下载这个php文件:dnspodupdate.zip
    5. 把该文件放在外网可以访问的空间里,比如http://www.xxx.com/api/dnspodupdate.php
    6. 在你的openwrt路由上安装ddns-scripts,有luci的装luci-app-ddns更方便;
    7. 登录路由,打开/usr/lib/ddns/services,添加
      "dnspod.com" "http://www.xxx.com/api/dnspodupdate.php?username=[USERNAME]&password=[PASSWORD]&domain=[DOMAIN]&myip=[IP]"
    8. 登录路由器管理界面,服务->动态DNS,服务提供商里会出现dnspod.com选项。如果没有luci,请修改/etc/config/ddns文件以达到同样效果。
      主机名:二级域名@顶级域名(比如你的二级域名是abc.xxx.com,那么该处就填写abc@xxx.com)(这样填luci可能不给保存,就手动改/etc/config/ddns文件吧)
      用户名:就是你的dnspod账户
      密码:就是你的dnspod密码
      网络:选wan
      点“保存并应用”,最好开启定时更新,间隔时间不要太短,5分钟就好。
    9. 重启路由就可以测试效果了。如果不想重启,根据openwrt的wiki,还可以执行
    ACTION=ifup INTERFACE=wan /sbin/hotplug-call iface

    来测试。

  • 轻松用wifi(承载网络)分享Win7/8的有线网络

    其实用wifi承载网络来分享有线网络这个途径不少人都是知道的,要么装一些第三方软件例如猎豹什么的(功能貌似相当强大),要么用几个cmd命令。

    我之前一直都是用cmd命令来搞的,不过对一些同学来说,难度有点高(我知道有同学买了360路由什么的..),尤其是网络的配置这个部分。所以我现学现卖写了这个软件。

    使用说明:

    1. 第一次使用建议点左上角配置一次承载网络,以前开启过的按左上角的菜单来进入向导,确保连上承载网络之后能上网。
    2. 由于本人技术问题,检测“是否支持”和“当前状态”这两个项目都只能用于简体中文版的系统,目前在Win7/8/8.1 x64均测试成功,其他语言的支持有待补充。
    3. 本程序理论上需要.NET Framework 4.5或以上的支持。

    功能暂时也就截图上这些了,有使用问题欢迎反馈。

    wifishare

    下载地址:hostednetwork.exe

    Changelog:

    ————————

    v1.0  2013.09.16

    [+]第一版

    ————————

    v1.1  2013.09.16

    [*]部分细节修改

    ————————

    v1.2  2013.10.13

    [*]教程部分图片更改

    ————————

    v1.3  2013.10.30

    [+]增加更新检查功能

    [*]增加逻辑判断,增强程序稳定性

    ————————

    v1.4  2013.11.2

    [+]换掉了原来的默认图标

    ————————

    v1.5  2013.11.25

    [+]增加“遇到问题”链接

    [*]又改了一下图标

    [*]优化更新检查逻辑

    ————————

    v2.0  2014.3.27

    [+]增加检测当前客户端功能

    [*]把整个程序用C#重写了一次,之前用VB.NET写的,感觉写简单的小程序还是用后者方便点啊

    ————————

    v2.2  2014.4.9

    [+]针对重新配置承载网络有时不成功的情况(例如无管理员权限),增加了cmd返回信息的反馈

    ————————

    v2.21  2014.5.6

    [+]打开程序时会要求获得管理员权限,避免了打开程序之后权限不足的问题

    [*]现在程序需要.NET Framework 4.5

    ————————

    v2.22  2014.7.23

    [*]最近在学一点C#,把检查更新的代码放到了线程里面,这样就避免了检查时程序卡顿的的问题

    ————————

    v2.23  2014.8.11

    [+]自动检查更新现在可以显示新版的更新内容,点确定可以直接下载

    ————————

    v2.29  2014.10.12

    [+]可以自动通过已连接的MAC地址检测对应客户端的IP和计算机名

    [*]增强了自动检查更新的稳定性

    ————————

    v2.3  2014.11.17

    [*]修改了获取客户端的IP和计算机名的逻辑

     

    ===============================

    出现问题?

    [error]连到系统上的设备没有发挥作用[/error]

    [important]请确定你的wifi硬件开关已打开。[/important]

    [error]设备无法连接Wi-fi[/error]

    [important]检查网络适配器的ip是否出现问题,如果是169.254开头的就是DHCP出现问题导致的,可以手动为它分配一个ip,设备也可以用固定ip的方式来连接Wi-fi[/important]