# pppd, pppoe 與 chroot , busybox 使用 Author: WhoAmI Date: 20220801 E-mail: kccddb@gmail.com Copyright: CC BY-NC-SA 這裡寫的是非標準 Fedo***, Deb***, Ubun***, 用法 你要看他們的標準用法, 那請別看這裡, 請離開別浪費時間, 這裡只有簡單但複雜的東西 --------------------------------------------------------------------------------------------------- 這裡的 ppp, rp-pppoe 都是自己 source compile, 沒有那些 adsl-start, adsl-stop, ... 那些東西 連 /etc/ppp/pap-secrets, /etc/ppp/chap-secret 都沒有 因此如要看他們的標準用法, 那也別看這裡了, 也請離開, 不用浪費時間 **************************************************************************************************** 以下 是 pppd 與 pppoe 的 DIY, 相信能看懂以下內容者的能力. 若想看Protocol 可以找其它資料. pppoe 事實上昰透過 Ethernet 進行 PPP 連線 /* pppd, pppoe * */ 這裡用的是很小的 Linux系統 (pppd, pppoe DIY) --------------------------------------------------------------------------------------------------------- pppd 很麻煩, 若不想改原來 HOST 設定需要 chroot 一起配合 以下是x86 版, 改成 Beaglebone, Sitara, Raspberry Pi...不是問題 編譯好 rp-pppoe, pppd , 其中 pppd pppoe也加入 PATH 中 laikc@laikc-virtual:~/x86/rp-pppoe-3.11$ pppd pty 'pppoe -I eth0 -T 100 -U -m 1412' linkname adsl0 user xxxxxx@hinet.net password xxxxxxxl default-asyncmap hide-password nodetach mtu 1492 -------------------------------------------------------------------------------------------------------------------- 上面xxxxxx部分自己改 Advanced user: linkname 也請看 Multiple PPPoE connections [sudo] password for laikc: Using interface ppp0 Connect: ppp0 <--> /dev/pts/5 PAP authentication succeeded local IP address 114.26.44.207 remote IP address 168.95.98.254 沒 DNS 因此再來 laikc@laikc-virtual:~/x86/rp-pppoe-3.11$ pppd pty 'pppoe -I eth0 -T 100 -U -m 1412' linkname adsl0 user xxxxxx@hinet.net password xxxxxxx default-asyncmap hide-password nodetach mtu 1492 usepeerdns Using interface ppp0 Connect: ppp0 <--> /dev/pts/5 PAP authentication succeeded local IP address 111.246.97.7 remote IP address 168.95.98.254 primary DNS address 168.95.192.1 secondary DNS address 168.95.1.1 但是這樣 route, 與 NAT 還不能動, 還有MTU 問題, MTU 以後再談, MTU 是可能的大問題 route, nat 是小問題, 除了多路 VPN bonding 與 load balancing ---------------------------------------------------------------------------------------- 您當然可以依照 pppd 的結果自己手動設定 routing, NAT 的問題, 但是 pppd 會始用 /etc/ppp/ip-up 幫忙設定, ppp-2.4.6 為例 source code --------------------------------------------------------------------------------------------------- static void ipcp_script(script, wait) char *script; int wait; { char strspeed[32], strlocal[32], strremote[32]; char *argv[8]; slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr); slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr); argv[0] = script; argv[1] = ifname; argv[2] = devnam; argv[3] = strspeed; argv[4] = strlocal; argv[5] = strremote; argv[6] = ipparam; argv[7] = NULL; if (wait) run_program(script, argv, 0, NULL, NULL, 1); else ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL, 0); } 內定使用 script #define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets" #define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets" #define _PATH_SRPFILE _ROOT_PATH "/etc/ppp/srp-secrets" #define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options" **#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up" #define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"** #define _PATH_IPPREUP _ROOT_PATH "/etc/ppp/ip-pre-up" #define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up" #define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down" #define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options." #define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors" #define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/" #define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf" pppd 啟動的環境變數 (當然正常只有 ...child process 可以用) Search for "script_setenv"..., 我用 Windows Jens' File Editor 找出來 E:\src\ppp-2.4.6\pppd\auth.c(974,5): script_setenv("PEERNAME", peer_authname, 0); E:\src\ppp-2.4.6\pppd\ipcp.c(1816,5): script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0); E:\src\ppp-2.4.6\pppd\ipcp.c(1818,2): script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1); E:\src\ppp-2.4.6\pppd\ipcp.c(1825,2): script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0); E:\src\ppp-2.4.6\pppd\ipcp.c(1827,2): script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0); E:\src\ppp-2.4.6\pppd\ipcp.c(1829,2): script_setenv("USEPEERDNS", "1", 0); E:\src\ppp-2.4.6\pppd\ipcp.c(1855,3): script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0); E:\src\ppp-2.4.6\pppd\ipcp.c(1861,3): script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0); E:\src\ppp-2.4.6\pppd\ipv6cp.c(1213,5): script_setenv("LLLOCAL", llv6_ntoa(go->ourid), 0); E:\src\ppp-2.4.6\pppd\ipv6cp.c(1214,5): script_setenv("LLREMOTE", llv6_ntoa(ho->hisid), 0); E:\src\ppp-2.4.6\pppd\main.c(339,5): script_setenv("ORIG_UID", numbuf, 0); E:\src\ppp-2.4.6\pppd\main.c(467,5): script_setenv("PPPLOGNAME", p, 0); E:\src\ppp-2.4.6\pppd\main.c(470,2): script_setenv("DEVICE", devnam, 1); E:\src\ppp-2.4.6\pppd\main.c(472,5): script_setenv("PPPD_PID", numbuf, 1); E:\src\ppp-2.4.6\pppd\main.c(742,5): script_setenv("IFNAME", ifname, iskey); E:\src\ppp-2.4.6\pppd\main.c(786,5): script_setenv("PPPD_PID", numbuf, 1); E:\src\ppp-2.4.6\pppd\main.c(832,5): script_setenv("LINKNAME", linkname, 1); E:\src\ppp-2.4.6\pppd\main.c(1249,5): script_setenv("CONNECT_TIME", numbuf, 0); E:\src\ppp-2.4.6\pppd\main.c(1251,5): script_setenv("BYTES_SENT", numbuf, 0); E:\src\ppp-2.4.6\pppd\main.c(1253,5): script_setenv("BYTES_RCVD", numbuf, 0); E:\src\ppp-2.4.6\pppd\main.c(1731,37): * exec. It is not possible to use script_setenv() or E:\src\ppp-2.4.6\pppd\main.c(2016,4): * script_setenv - set an environment variable value to be used E:\src\ppp-2.4.6\pppd\main.c(2020,1):script_setenv(var, value, iskey) E:\src\ppp-2.4.6\pppd\multilink.c(188,3): script_setenv("BUNDLE", bundle_id + 7, 1); E:\src\ppp-2.4.6\pppd\multilink.c(222,4): script_setenv("BUNDLE", bundle_id + 7, 0); E:\src\ppp-2.4.6\pppd\multilink.c(235,2): script_setenv("BUNDLE", bundle_id + 7, 1); E:\src\ppp-2.4.6\pppd\plugins\radius\radius.c(596,16): script_setenv("RADIUS_FILTER_ID", vp->strvalue, 1); E:\src\ppp-2.4.6\pppd\plugins\radius\radius.c(600,16): script_setenv("RADIUS_FRAMED_ROUTE", vp->strvalue, 1); E:\src\ppp-2.4.6\pppd\plugins\rp-pppoe\plugin.c(221,5): script_setenv("MACREMOTE", remote_number, 0); E:\src\ppp-2.4.6\pppd\tty.c(739,2): script_setenv("SPEED", numbuf, 0); ----------------------------------------------------------------------------------------------------------------- 重要的就是上面紅色這兩個, 其餘沒有也沒關係, 直接用 pppd command #define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up" #define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down" 可以來設定 route, 與 NAT, 等, 其餘再說, 很煩的... 設計網路設備的 BUNDLE 應該很有興趣吧? 哈, 其實還有很多要寫程式要配合沒那麼簡單 ....真正實用也非 如此簡單 up ,down..... 為了打造與原來 Host Linux 無關的 rootfs 我們用了最簡單的 busybox, 放在 home/x86 中, tftpboot 不用理, 那是我 pxe, 與 tftp 用的 root@laikc-virtual:/home/laikc/x86# chroot . bin/sh / # ls ib tftp.sh usr linuxrc bin sbin tftpboot etc src tmp exit 後 ------------------------------------------------------------------- src 都是放該 cpu arch 的 source, 有些要改makefile root@laikc-virtual:/home/laikc/x86# mkdir proc sys dev var 因為用 host 的系統, 因此 mount 原來 3 個主要系統, 若是真正版子, 要自己來, 不是用以下的 command, 也就是proc, dev, sys 要自己來 chroot pppd 注意事項: 因為pppd 用了一堆kernel device 功能, 因此須要額外 proc, sys, dev 請看 ppp source code ******************************************************** 設定 dev, proc, sys ******************************************************** root@laikc-virtual:/home/laikc/x86# mount -t proc proc proc/ root@laikc-virtual:/home/laikc/x86# mount --rbind /sys sys/ root@laikc-virtual:/home/laikc/x86# mount --rbind /dev dev/ *** **--rbind "Bind Mounts" recursive bind mount. Please see wiki. Maybe you must know this problem in detail.** *** ---------------------------------------------------------------------------- 看 pppd source 也需要 var/run root@laikc-virtual:/home/laikc/x86# mkdir var/run 因為 pppd 需要 proc, dev, sys (kernel modules), var, var/run 很多程式需要 /var, /var/run , embedded system 可用 ramdisk mount /var, /tmp 我把 pppd pppoe dynamic lib 都cp 至 root@laikc-virtual:/home/laikc/x86/lib 還有 linux-gate.so.1是 kernel 的, 不用 cp laikc@laikc-virtual:~/x86$ ldd bin/pppoe linux-gate.so.1 => (0x00634000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x0072e000) /lib/ld-linux.so.2 (0x00bfb000) laikc@laikc-virtual:~/x86$ ldd bin/pppd linux-gate.so.1 => (0x00bbb000) libcrypt.so.1 => /lib/i386-linux-gnu/libcrypt.so.1 (0x00d2e000) libutil.so.1 => /lib/i386-linux-gnu/libutil.so.1 (0x002ce000) libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0x00ff5000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x008b6000) /lib/ld-linux.so.2 (0x0081f000) laikc@laikc-virtual:~/x86$ --------------------------------------------------------------------------------------------- **chroot . bin/sh** (因為我的busybox 沒有 bash, lubutu12.04 chroot 內定 /bin/bash 因此要加 shell, 如果您只用 chroot . 會出問題, 沒有shell ) 這樣您的root 就是/home/laikc-virtual:/home/laikc/x86 您的/home/laikc-virtual:/home/laikc/x86/bin 要有 sh ------------------------------------------------------------------------------------------- 沒設 PATH 就要完整 path /bin/pppd pty '/bin/pppoe -I eth0 -T 30 -U -m 1412' linkname adsl2 user xxxxxxxxx password xxxxxxx default-asyncmap hide-password nodetach mtu 1492 usepeerdns Connect: ppp0 <--> /dev/pts/5 PAP authentication succeeded local IP address 111.246.97.7 remote IP address 168.95.98.254 primary DNS address 168.95.192.1 secondary DNS address 168.95.1.1 這樣您就可以寫自己的 ip-up 與 ip-down 與原HOST Linux 沒有衝突 其實您看 ppp source, 沒有那些 script 也可以自己改 ------------------------------------------------------------------------------------------------------------- 做這個不是很無聊嗎? 不是的! 因為與網路相關先用 x86 測完再移植 別的 CPU 比較方便, 實際不是每人手有一片版子, 真正最跨平台的是 C. Java 只是應用層, import LIB 不一樣, java 能跨平台嗎? 累死人, 您把 C# 移植Android 看看? 但是 C 很好移植. 簡單原則: 與UI 無關用 C, 與UI 有關可用 Java等 ------------------------------------------------------------------------------------------------------------- 還有 Linux IEEE80211 wifi 也可以如此使用來測試, 沒有udev, 就要手動 insmod -------------------------------------------------------------------------------------------------------------- ip-up , ip-down 寫法請看 http://wiki.openwrt.org/doc/howto/vpn.client.pptp 很好資料, 這就不提了, 上面寫的很好, 雖然非PPPoE, 原理一樣 pppd 有點複雜的~~這老的好東西, 可以用到現在~~ 但是 route 請改 ip route (check replace parameters ), 不要用 route 了 ................................................................................................................................ 正常檢察網路通不通不是用ping 固定IP方法, 檢察WAN網路斷線也不是只用 ifconfig 方法 其中有用的方法 AF_PACKET (不是用ping) 與 Netlink Socket 判斷 route change