2014年6月6日 星期五

[Linux] 使用 nc 測試 TCP Port 是否正常 @ Ubuntu 12.04

最近在構想一個架構,在遠方 Data Center 架一個 MySQL Server ,但又在本地端架一個備份機制。當連不到遠端時,改連本地機器,所以,就需要偵測遠方 MySQL Server 的狀態。

於是乎...就是用 nc 指令來達成:

$ nc -z -w 3 remote_server 3306 && echo "OK"

其中 -w timeout 機制。

2014年6月5日 星期四

iOS 開發筆記 - DNS Lookup、Host name to IP Address

最近想把玩一下 socket ,過程中需要把 domain name 轉成 ip ,筆記一下:

#include <netdb.h>
#include <arpa/inet.h>

- (NSString*)hostnameToIPAddress:(NSString*)hostname
{
    struct hostent *remoteHostEnt = gethostbyname([hostname UTF8String]);
    struct in_addr *remoteInAddr = (struct in_addr *) remoteHostEnt->h_addr_list[0];
    return [NSString stringWithUTF8String:inet_ntoa(*remoteInAddr)];
}

NSLog(@"IP: %@", [self hostnameToIPAddress:@"tw.yahoo.com"]);
NSLog(@"IP: %@", [self hostnameToIPAddress:@"tw.yahoo.com"]);
NSLog(@"IP: %@", [self hostnameToIPAddress:@"tw.yahoo.com"]);


若看到查到結果不一樣,主因是 DNS 提供的分流服務。

2014年6月4日 星期三

iOS 開發筆記 - 初學 Swift 與 Storyboard 互動方式,以 UITableViewController 和 prepareForSegue 為例



WWDC 2014 讓 Swift 出世見人,想學習的可先看 Apple 官網 Swift 文件:The Swift Programming Language,大概只要看完 A Swift Tour 即可有基本功力,看完心得:簡潔有力。接著,就可以看看 Using Swift with Cocoa and Objective-C 這份了,也是此次筆記項目。

首先下載 Xcode 6 beta 下來用,新增 Project 時,選用 Swift 程式語言,這時的程式架構就是 Swift 語法,與 Objective-C 大同小異,初次看還滿清爽的。

AppDelegate:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
                         
    var window: UIWindow?


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    func applicationWillResignActive(application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(application: UIApplication) {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

}


ViewController:

import UIKit

class ViewController: UIViewController {
                         
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}


接著,則是使用 Storyboard,承襲之前用 Xcode 開發的模式,新增元件後,可以拖拉到對應的程式碼(此例為 ViewController),就可以填寫一些 Code 了。

例如 UIButton 行為:

    @IBOutlet var button : UIButton
 
    @IBAction func myClick(sender : AnyObject) {
        println("Click")
        button.setTitle("change", forState: UIControlState.Normal);
    }


例如 UITableViewController :

import UIKit

class MyTableViewController: UITableViewController {
    var dataList = String[]()
 
    override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
        return 1
    }
 
    override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
        return dataList.count
    }
 
    override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
     
        var cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
     
        cell.text = dataList[indexPath.row]
     
        return cell
    }
 
}


以及 prepareForSegue 的用法:

    override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
        if segue.identifier.compare("showTable") == 0 {
            if segue.destinationViewController.isKindOfClass(MyTableViewController) {
                // Type 'AnyObject!' cannot be implicitly downcast to 'UIViewController'
                // var vc:UIViewController = segue.destinationViewController

                var tvc:MyTableViewController = segue.destinationViewController as MyTableViewController
             
                tvc.dataList.append("Hello")
                tvc.dataList.append("World")
            }
        }
    }


以上的小練習,就可以用 Swift 跟 Storyboard 切換 ViewController 等行為,而 UITableViewController 也稍微用了一下。

最後一提,目前使用 Swift 開發的不習慣之處:AutoComplete ! 沒了這招就真的等於砍掉重練了,試用的結果,不是按了 "." 之後會彈跳出來,而是要打 "->" 才會出現 Orz 我想應該還有不少待釐清的用法。

2014年6月3日 星期二

[Linux] Allow from localhost 失效 @ Ubuntu 14.04 / Apache 2.4.7

[Linux] Allow from localhost 失效 @ Ubuntu 14.04 / Apache 2.4.7

週末把某檯機器更新後,發現原先寫的 apache.conf 失效,主要是 Allow from localhost 這段:

<Directory /data/path>
AuthType Basic
AuthName "Password Required"
AuthUserFile /path/auth_pass

Order allow,deny
Allow from localhost
# Allow from DeviceIP


Satisfy any
</Directory>


直到我加上 DeviceIP 後才行。

$ wget -O /dev/null http://localhost/service/api
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:443... connected.
WARNING: no certificate subject alternative name matches
        requested host name ‘localhost’.
HTTP request sent, awaiting response... 401 Unauthorized

Username/Password Authentication Failed.


追了一下,發現是 iptables 的設定,把這條拿掉就行了:

iptables --table nat --append POSTROUTING --jump MASQUERADE

此筆記是用來記錄,iptables 的影響 Orz

2014年6月1日 星期日

Apple TV 3 以及觀看大陸頻道的原理



前陣子在 PCHOME 特價時下標了 XD 其實觀望許久,甚至在露天也時時觀望著,總之,家裡就又多了一台 Apple Device 了 :P

這陣子一直都只使用 AirPlay 的方式,記得曾聽別人說可以直接觀看大陸影音網站,就隨意找了一下,使用之後,大概猜測的 Hack 原理:
  • 原先 Apple TV 有提供"預告片"的機制,既然這是個動態內容,猜大概是要透過 API 到遠端 Server 要資料,因此,透過這個管道替換掉 "預告片" 的內容
  • 透過 DNS 的方式,讓 API 查詢對象從 Apple Server 換到私人機器
然而,在 2013 年中之後,Apple TV 稍作修正,查詢的 API 都改走 HTTPS 方式,導致透過 DNS 更換 API 查詢對象失敗,但解法仍有:
  • 更換 Apple TV 內,對 Apple Server 的憑證內容,以此又破壞掉 HTTPS 保護
這場路一直走下去,只要硬體沒有被保護,那應該就可以一直玩下去了,此次 Apple TV 硬體方面,其實是透過 Apple OSX App Store 的官方工具修改的,如憑證資訊。

此外,在台灣若要觀看大陸內影音網站,則必須透過 Proxy 的機制,而影音網站大多的保護方式在於"取得影片播放清單m3u8"的那個步驟做 IP 管制,而非 video binary data 的取得,所以,網路上就有一些解法讓 Chrome/Firefox 就可以觀看到大陸影音。



測試流程:
  1. 更改 DNS (180.153.225.136)
  2. 更改 Apple TV HTTPS 憑證
    1. 下載 appletv-fix.mobileconfig
    2. 使用 Apple Configurator 使用全域 HTTP 代理伺服器 (http://yo.uku.im/proxy.pac)
  3. 當 Apple TV 開機好後,透過 MicroUSB 線連接
  4. 透過 Apple Configurator 將設定新增至 Apple TV
如此一來,點選"預告片"時,就可以看到對岸客製化的服務:


最後一提,因為上述流程改變了 Apple HTTPS 憑證資訊(其實 Proxy server 也能做到一些),因此,建議不要再登入 iTunes Store了,畢竟已經無法保證你是否是跟真正 Apple Service 連結,還是跟大陸的私人機器溝通,會有帳密安全性問題。

相關資料: