Obfuscated SSH tunnel

VPN providers were cracked down, open source anti-censorship tools were eliminated. This is what’s happening in China and has become even more severe than ever. Shadowsocks alone is no longer reliable due to more powerful deep packet inspection implemented at the GFW.

I am now replacing shadowsocks on my gateway with obfuscated SSH tunnel, based on Tor‘s obfsproxy. To the impatient ones, I will first give a concise summary of the necessary steps of my set up. You can follow it without drilling down the details. I will explain in more details later. But please note that you have to follow the other instructions in this blog post to complete the whole set up.

Quick Set up

On your server

Assume your server runs Debian 8 (jessie) or Ubuntu, and its IP is 1.2.3.4, run these commands:

$ sudo apt-get install obfsproxy
$ mkdir /tmp/obfsproxy-temp
$ obfsproxy --data-dir=/tmp/obfsproxy-temp scramblesuit --password=QWLY42YHB75J3B57XOKYNNFJPOQ7APHL --dest=127.0.0.1:22 server 0.0.0.0:7700
On Raspberry Pi gateway
$ sudo apt-get install python-dev
$ sudo pip install obfsproxy

Edit ~/.ssh/config:

Host 1.2.3.4
  ProxyCommand nc -X 5 -x 127.0.0.1:3333 %h 7700

Run these commands:

$ obfsproxy --log-file=obfsproxy.log --log-min-severity=info scramblesuit --password=QWLY42YHB75J3B57XOKYNNFJPOQ7APHL socks 127.0.0.1:3333
$ ssh user@1.2.3.4 -N -D 1080

Boost WIFI Speed by Forcing 40 MHz Channels in hostapd on RPi

802.11n can double the channel bandwidth of 802.11g from 20 MHz to 40 MHz, but this operation mode is not recommended in areas that the spectrums are congested and likely interfere with existing WIFI and bluetooth devices. As a result, hostapd will not enable 40 MHz when it finds other channels are being used, like what is seen from the hostapd log below:

nl80211: New scan results available
nl80211: Received scan results (16 BSSes)
40 MHz affected channel range: [2397,2447] MHz
Neighboring BSS: 1c:fa:68:8e:a6:e0 freq=2412 pri=1 sec=5
Neighboring BSS: e0:05:c5:4c:e2:b6 freq=2427 pri=0 sec=0
Neighboring BSS: b0:48:7a:6a:9d:32 freq=2437 pri=6 sec=10
40 MHz pri/sec mismatch with BSS b0:48:7a:6a:9d:32 <2437,2457> (chan=6+) vs. <2412,2432>
20/40 MHz operation not permitted on channel pri=1 sec=5 based on overlapping BSSes

However, this is unrealistic in modern cities. You should be grateful the primary channel you choose has not been used already, let alone the additional one for 40 MHz. What can we do? We have to force hostapd to turn on 40 MHz anyway. But since hostapd does not have any configuration options for that, we have to recompile hostapd from source. Actually, this has been done in other distros. For example, OpenWRT and Arch has patched their hostapd with the noscan patch, which adds an option to force 40MHz mode regardless of the environment.

Before turning on 40 MHz, the iwconfig on my laptop is like this, notice the bit rate is only 54 Mb/s:

wlan0     IEEE 802.11abgn  ESSID:"bibiworld"  
          Mode:Managed  Frequency:2.437 GHz  Access Point: C8:3A:35:C9:17:4A   
          Bit Rate=54 Mb/s   Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=70/70  Signal level=-32 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:30  Invalid misc:683   Missed beacon:0

Now let us start. First you need to add a deb-src source to apt so that we can download source packages. Note that I am still using Raspbian Wheezy. If you use Jessie, change the deb-src line according to your original deb line.

pi@raspberrypi $ echo "deb-src http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi" \
 | sudo tee /etc/apt/sources.list
pi@raspberrypi $ sudo apt-get update
pi@raspberrypi $ apt-get source hostapd            # download source of hostapd
pi@raspberrypi $ apt-get build-dep hostapd    # download all build dependencies
pi@raspberrypi $ cd wpa-1.0

Save the following patch into a file:

--- wpa-1.0.orig/src/ap/hw_features.c      2012-05-10 05:56:09.000000000 +0800
+++ wpa-1.0/src/ap/hw_features.c        2015-07-18 17:22:37.788215009 +0800
@@ -430,6 +430,7 @@
                oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
        wpa_scan_results_free(scan_res);
 
+#if 0
        if (!oper40) {
                wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on "
                           "channel pri=%d sec=%d based on overlapping BSSes",
@@ -439,6 +440,12 @@
                iface->conf->secondary_channel = 0;
                iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET;
        }
+#endif
+       wpa_printf(MSG_INFO, "Force 20/40 MHz operation on "
+                  "channel pri=%d sec=%d even there are overlapping BSSes",
+                          iface->conf->channel,
+                          iface->conf->channel +
+                          iface->conf->secondary_channel * 4);
 
        res = ieee80211n_allowed_ht40_channel_pair(iface);
        hostapd_setup_interface_complete(iface, !res);
pi@raspberrypi $ patch -p1 < patch.diff

Because we are going to create a new hostapd package, it'd be a good practice to increment the version number by adding a new section at the top of debian/changelog, like this:

wpa (1.0-3+deb7u3) wheezy; urgency=low

  * Force 20/40 MHz.

 -- Anthony Wong   Sat, 18 Jul 2015 16:30:43 +0800

wpa (1.0-3+deb7u2) wheezy-security; urgency=high
...

Now we are ready to compile the packages:

pi@raspberrypi $ fakeroot debian/rules binary

If it succeeds, install the new package with dpkg -i.

Restart hostapd, it should now force 40 MHz mode:

nl80211: New scan results available
nl80211: Received scan results (23 BSSes)
40 MHz affected channel range: [2397,2447] MHz   
Neighboring BSS: e0:05:c5:4c:e2:b6 freq=2427 pri=0 sec=0
Neighboring BSS: 00:d0:41:c4:25:31 freq=2437 pri=6 sec=2
40 MHz pri/sec mismatch with BSS 00:d0:41:c4:25:31 <2437,2417> (chan=6-) vs. <2412,2432>
Force 20/40 MHz operation on channel pri=1 sec=5 even there are overlapping BSSes
HT40: control channel: 1  secondary channel: 5
Completing interface initialization

And my iwconfig output now shows Bit Rate is 150 Mb/s, yay!

wlan0     IEEE 802.11abgn  ESSID:"bibiworld"  
          Mode:Managed  Frequency:2.412 GHz  Access Point: C8:3A:35:C9:17:4A   
          Bit Rate=150 Mb/s   Tx-Power=15 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=70/70  Signal level=-28 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:31  Invalid misc:330   Missed beacon:0

Deploy Shadowsocks on Raspberry Pi with ChinaDNS and Redsocks

Assume you already have a Raspberry Pi configured as a WIFI router like mine shown below, but you live in China and have to deal with the fact that many websites can’t be accessed due to GFW. Don’t be despair and with some hacking you can get your Internet freedom back.

IMG_20150714_134341

The mechanism is to use shadowsocks on your router which directs any traffic to a shadowsocks server in the free world. It’s simple to get it up and running on a local machine, but on a router you need to use redsocks to redirect traffic to the shadowsocks client running on your Raspberry Pi. DNS traffic has to be routed by redsocks as well otherwise your DNS replies will be contaminated. To remain as fast as normal when accessing China websites you also need to skip routing traffic to Redsocks for anything within the China IP ranges. Even if you don’t care about performance, this is still necessary in some circumstances like geoip restriction such as tv.sohu.com does not deliver contents if you live outside of China.

Finally, we want to improve the performance even further by using ChinaDNS. To avoid DNS poisoning, we can always resolve DNS over our secured shadowsocks connection, but this is not optimal if a China website have CDNs outside China. ChinaDNS queries local DNS servers to resolve Chinese domains and queries foreign DNS servers to resolve foreign domains, and from my testing it is useful to avoid DNS poisoning with the “DNS compression pointer mutation” option. (Update: I have switched from ChinaDNS to dnsmasq+dnscrypt, please read Securing DNS Traffic in China to see how it works.)

Shadowsocks

I assume that you have shadowsocks server running on a public server, so I will skip that part and only talk about the client side.

Installing shadowsocks is very simple, note that it will be installed under /usr/local/.

pi@raspberrypi $ sudo apt-get install python-pip
pi@raspberrypi $ sudo pip install shadowsocks
Downloading/unpacking shadowsocks
  Running setup.py egg_info for package shadowsocks
    
Installing collected packages: shadowsocks
  Running setup.py install for shadowsocks
    
    Installing sslocal script to /usr/local/bin
    Installing ssserver script to /usr/local/bin
Successfully installed shadowsocks
Cleaning up...

Start up shadowsocks while listening on local port 1080:

pi@raspberrypi $ sslocal -s  -p  -k  -b 127.0.0.1 -l 1080

Redsocks

Install redsocks, simply apt-get from the archive:

pi@raspberrypi $ sudo apt-get install redsocks

Then you need to change the START option in /etc/default/redsocks from NO to YES, so that redsocks will start automatically at boot time and also can be started by sudo /etc/init.d/redsocks start:

pi@raspberrypi $ sudo vi /etc/default/redsocks
START=yes

Then update /etc/redsocks.conf. Most of the default settings work fine, just need to change local_ip in the redsocks section to your address of the network interface that accepts traffic from your local network. The default is 127.0.0.1, but that does not work well if you want to re-route traffic from other machines on your network, so change it to something like:

redsocks {
        /* `local_ip' defaults to 127.0.0.1 for security reasons,
         * use 0.0.0.0 if you want to listen on every interface.
         * `local_*' are used as port to redirect to.
         */
        local_ip = 192.168.0.1;
        local_port = 12345;
        ...
}

But we want traffic from other hosts in your network to be redirected by redsocks to your local shadowsocks client, which in turn sent to the the remote shadowsocks server. We need to pay special attention to DNS traffic, as DNS poisoning is prevalent in China. We need to take special care to redirect DNS traffic through redsocks/shadowsocks.

We also want all China traffic NOT to go through shadowsocks for performance. This can be easily done by looking at the destination IP, if it is in the China IP range we skip going through the REDSOCKS china. First we need to get all network segments allocated to China and save it to a file called chnroute.txt:

pi@raspberrypi $ curl 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | grep ipv4 | grep CN | awk -F\| '{ printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > chnroute.txt

These all can be accomplished by iptables. You need to run the following iptables commands, or put them in a local script and run it with sudo.

# Specify your shadowsocks server
SS_SERVER_IP=11.22.33.44

iptables -t nat -N REDSOCKS  # Create a new chain called REDSOCKS

# Do not redirect to shadowsocks server
iptables -t nat -A REDSOCKS -d $SS_SERVER_IP -j RETURN

# Do not redirect local traffic
iptables -t nat -A REDSOCKS -d 0.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 10.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 127.0.0.0/8 -j RETURN
iptables -t nat -A REDSOCKS -d 169.254.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 172.16.0.0/12 -j RETURN
iptables -t nat -A REDSOCKS -d 192.168.0.0/16 -j RETURN
iptables -t nat -A REDSOCKS -d 224.0.0.0/4 -j RETURN
iptables -t nat -A REDSOCKS -d 240.0.0.0/4 -j RETURN

# China traffic does not go through REDSOCKS
while read subnet; do
  sudo iptables -t nat -A REDSOCKS -d $subnet -j RETURN
done < /tmp/chnroute.txt

# Redirect all TCP traffic to redsocks, which listens on port 12345
iptables -t nat -A REDSOCKS -p tcp -j REDIRECT --to-ports 12345

# These traffic go to REDSOCKS chain first
iptables -t nat -A PREROUTING -p tcp -j REDSOCKS

Run iptables -t nat -L -n to make sure the rules have been added correctly. Now start up redsocks by sudo /etc/init.d/redsocks start and let's test it out by doing some web browsing on another computer in your local network. If that works fine, congratulations and you have set up everything correctly! If not, look at shadowsocks output and also turn on redsock's log_debug and check if there is anything useful in /var/log/daemon.log.

ChinaDNS

ChinaDNS is not absolutely necessary, but as explained at the beginning it is desirable. There is no pre-built package so we need to compile it. It is simple to do:

pi@raspberrypi $ sudo apt-get install git automake
pi@raspberrypi $ git clone https://github.com/clowwindy/ChinaDNS.git
Cloning into 'ChinaDNS'...
remote: Counting objects: 815, done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 815 (delta 0), reused 0 (delta 0), pack-reused 810
Receiving objects: 100% (815/815), 213.52 KiB | 111 KiB/s, done.
Resolving deltas: 100% (426/426), done.

pi@raspberrypi $ ./autogen.sh
pi@raspberrypi $ ls
aclocal.m4  autom4te.cache  chnroute.txt  configure     COPYING  install-sh  Makefile.am  missing  packaging  src
autogen.sh  CHANGES         config.h.in   configure.ac  depcomp  iplist.txt  Makefile.in  openwrt  README.md  tests

pi@raspberrypi $ ./configure 
...
pi@raspberrypi $ make
...

After it is successfully compiled, test it out:

pi@raspberrypi $ sudo src/chinadns
pi@raspberrypi $ host video.sina.com.cn 
video.sina.com.cn has address 58.63.237.200
pi@raspberrypi $ host www.youtube.com
www.youtube.com is an alias for youtube-ui.l.google.com.
youtube-ui.l.google.com is an alias for youtube-ui-china.l.google.com.
youtube-ui-china.l.google.com has address 46.82.174.68
youtube-ui-china.l.google.com has IPv6 address 2404:6800:4005:80b::200e
pi@raspberrypi $ sudo src/chinadns -m -c chnroute.txt
pi@raspberrypi $ host video.sina.com.cn 
video.sina.com.cn has address 123.125.22.225
pi@raspberrypi $ host www.youtube.com
www.youtube.com is an alias for youtube-ui.l.google.com.
youtube-ui.l.google.com is an alias for youtube-ui-china.l.google.com.
youtube-ui-china.l.google.com has address 74.125.203.138
youtube-ui-china.l.google.com has address 74.125.203.100
youtube-ui-china.l.google.com has address 74.125.203.113
youtube-ui-china.l.google.com has address 74.125.203.139
youtube-ui-china.l.google.com has address 74.125.203.101
youtube-ui-china.l.google.com has address 74.125.203.102
youtube-ui-china.l.google.com has IPv6 address 2404:6800:4005:808::200e

If it goes well, run src/chinadns -m -c chnroute.txt when your router boots.

That's it! I hope these are useful to you.

Update: I have switched from ChinaDNS to dnsmasq+dnscrypt, please read Securing DNS Traffic in China to see how to set it up.

解決 WordPress 中 Google Web Font 被 GFW 屏蔽問題

自從本 blog 的 wordpress 升級並更換 theme 後,偶爾發現 page load 得很慢,用 chrome 自帶的 developer tool 查了一下才發現原來 theme 用了 google web font,因爲 google service 被牆了所以在大陸瀏覽就像卡住了一樣。由於我絕大部份時間都是科學上網,所以一開始沒有發現問題。

Google font is blocked in China

既然 google web font 不能用,最簡單就是乾脆不用,把相關代碼拿掉就行,不過這樣做的後果是網站會極其難看。上策還是把 google web font 放到 wordpress server,再將 CSS 配置好。Google 一下發現有個很棒的 shell script 能幫個大忙:https://neverpanic.de/blog/2014/03/19/downloading-google-web-fonts-for-local-hosting/,它能幫你把需要的字體下載下來並產生一個立馬能用的 CSS 文檔。

WordPress 最少有兩個地方會加載 google web font,第一是 wordpress 本身用到的 Open Sans,另外是個別 theme 可能會用到的字體。視乎你的 theme 有沒有用 google font,有可能兩個地方都要處理。

目前我用的 theme 基於 twentyfourteen(我把原來左邊的 navigation 拿掉,header 加了 facebook, twitter 等幾個 icon),best practice 是在 wordpress 的 themes 目錄開一個叫 twentyfourteen-child 的新目錄,裏面只放用來 override parent theme 的東西。

解決問題的具體步驟如下:

  1. 下載剛才介紹過的網站的 shell script,我把它命名爲 downloadgooglefont.sh
  2. 先下載 wordpress 會下載的所有 Open Sans 字體(包括不同粗幼和斜體),在 downloadgooglefont.sh 裏要指定它們:
    families+=('Open Sans:300')
    families+=('Open Sans:400')
    families+=('Open Sans:600')
    families+=('Open Sans:300italic')
    families+=('Open Sans:400italic')
    families+=('Open Sans:600italic')
  3. 針對你使用的 theme,需要把 theme 用到的 google 字體寫進去。你要查一下你的 theme 會用到什麼字體,例如 twentyfourteen 會用到的字體在
    themes/twentyfourteen/functions.php

    的 215 行有提到:

                            
         'family' => urlencode( 'Lato:300,400,700,900,300italic,400italic,700italic' ),
    

    總共有7個字體,所以 script 需要加上:

    families+=('Lato:300')
    families+=('Lato:400')
    families+=('Lato:700')
    families+=('Lato:900')
    families+=('Lato:300italic')
    families+=('Lato:400italic')
    families+=('Lato:700italic')
    
  4. 執行該 script:
    $ bash ./downloadgooglefont.sh
    Downloading Open Sans:300... eot woff ttf svg 
    Downloading Open Sans:400... eot woff ttf svg 
    Downloading Open Sans:600... eot woff ttf svg 
    Downloading Open Sans:300italic... eot woff ttf svg 
    Downloading Open Sans:400italic... eot woff ttf svg 
    Downloading Open Sans:600italic... eot woff ttf svg 
    Downloading Lato:300... eot woff ttf svg 
    Downloading Lato:400... eot woff ttf svg 
    Downloading Lato:700... eot woff ttf svg 
    Downloading Lato:900... eot woff ttf svg 
    Downloading Lato:300italic... eot woff ttf svg 
    Downloading Lato:400italic... eot woff ttf svg 
    Downloading Lato:700italic... eot woff ttf svg

    這些就是下載完的所有文檔,包括適用於 chrome/chromium, firefox, safari 會用到的字體,還有一個 CSS file:

    Lato_300italic.svg
    Lato_300italic.ttf
    Lato_300italic.woff
    Lato_300.svg
    Lato_300.woff
    Lato_400italic.svg
    Lato_400italic.ttf
    Lato_400italic.woff
    Lato_400.svg
    Lato_400.ttf
    Lato_400.woff
    Lato_700italic.svg
    Lato_700italic.ttf
    Lato_700italic.woff
    Lato_700.svg
    Lato_700.ttf
    Lato_700.woff
    Lato_900.svg
    Lato_900.ttf
    Lato_900.woff
    LNM3t2QINm
    Open_Sans_300italic.svg
    Open_Sans_300italic.ttf
    Open_Sans_300italic.woff
    Open_Sans_300.svg
    Open_Sans_300.ttf
    Open_Sans_300.woff
    Open_Sans_400italic.svg
    Open_Sans_400italic.ttf
    Open_Sans_400italic.woff
    Open_Sans_400.svg
    Open_Sans_400.ttf
    Open_Sans_400.woff
    Open_Sans_600italic.svg
    Open_Sans_600italic.ttf
    Open_Sans_600italic.woff
    Open_Sans_600.svg
    Open_Sans_600.ttf
    Open_Sans_600.woff
    font.css
  5. 把上面所有的字體上傳到 wordpress server 的 wp-content/themes/twentyfourteen-child/ 目錄。
  6. 把 font.css 複製到 wp-content/themes/twentyfourteen-chile/style.css。
  7. 由於 twentyfourteen 在 functions.php 通過 wp_enqueue_style 加上 fonts.googleapis.com 的 link 來加載 Lato 字體,要想辦法把它拿掉:
            // Add Lato font, used in the main stylesheet.
            wp_enqueue_style( 'twentyfourteen-lato', twentyfourteen_font_url(), array(), null );
    

    不過我不喜歡直接修改 parent theme,所以我選擇在 twentyfourteen-child 把它 dequeue 掉。注意 add_action 的 priority 必須低於 10,dequeue 才會成功。theme_enqueue_styles 的前兩行是用來禁止 Open Sans 字體從 google server 加載,第3行才是禁止 Lato。
    _twentyfourteen-child/functions.php:

Osaka, Kyoto and Nara Travel Tips

Kiyomizu Dera (清水寺)
Kiyomizu Dera (清水寺)

After more than 10 years I traveled to Japan again. This time I went with my wife to Kyoto, Nara and Osaka. Here are some tips about travelling to these areas I want to share and also serve as notes to myself if I will ever go there again in future, which I will definitely do as Kansai is so beautiful and relaxing.

Keep connected

Getting mobile internet connection was not easy in the past since you need Japan residency to get a SIM from telco, but nowadays the market is more open and there are now many options. In this travel, I used a SIM card called Fuji card (富士卡), which I bought from Taobao at 76 CNY (about 1450 JPY or 12 USD). This card has 1.8GB 3G data, valid for 7 days, but does not have any voice call and cannot be recharged after you have used it up. This card is backed by China Unicom and Softbank, in my experience the data connection and coverage is very good. If you live in Hong Kong, you can find this card in Sham Shui Po as well.

“Fuji” SIM card (富士卡)
“Fuji” SIM card (富士卡)

If this card does not suit your purpose, you can find other alternatives:

  1. Fuji card has a cheaper sibling which has 1GB data only, sold at 66 CNY, and a more expensive sibling which has double the data to 3.2GB, sold at 155 CNY.
  2. Before the existence of Fuji card, there was Sakura card (櫻花卡). Sakura card still exists and offers 3GB of data with 7-day validity. From what I read it is slower than Fuji card’s 7.2Mbps and lesser coverage.
  3. There is also a nameless SIM which offers unlimited data. The first 100MB data each day uses 3G speed but afterwards it falls back to 2G speed. It is cheaper but I bet no one want to suffer from slow speed especially during traveling.
  4. If your phone does not support WCDMA or you are not good at fiddling mobile phone settings, you can rent a WIFI router. More expensive, and you have to return it after the trip which I find inconvenient.
  5. So-net also sells pre-paid SIM cards at the airport, at a higher price than the Fuji card.

About Hotel

Valentine’s day is not a good day to travel to Japan not (just) because restaurants are fully booked but room rates could be more expensive than normal days 2 to 3 times, even for budget hotels like Toyoko Inn. I was very lucky that I found a really nice ryokan called Kitanoya (北野家) where the rates remained the same on the special day. Only available at Jalan, so knowing some basic Japanese is a pre-requisite. In general, check Jalan and Airbnb and you might find hidden gems.

Kitanoya (北野家)
Kitanoya (北野家)

Hotel near Kansai Airport

My flight landed almost at midnight so I chose to stay in a hotel close to the airport and began our journey the next day. There are not many options, the hotel at the airport is too expensive so I chose to stay at First Hotel. It is located in Izumisano (泉佐野) and very close to the Izumisano railway station, so you can take a train there, or if it is too late like my case, you can take the late night airport bus, the last stop is exactly the Izumisano railyway station.

The bus station is just outside the exit of the departure hall. After exiting the airport, turn right, look for the stand numbered ’12’. No need to buy ticket beforehand, pay when you take off, so better make sure you have 1000 yen notes or coins, which I did not have. Luckily the bus driver was able to find a lady who had ten 1000 yen notes to change for my 10000 yen note, otherwise I don’t know what would end up.

Travel to/from Kansai Airport/Kyoto

If your destination is either Osaka or Kyoto and your flight will land at the Kansai International airport, you will likely buy the “ICOCA and Haruka” ticket set to take advantage of the Haruka train (non-reserved seat) from airport to Osaka or Kyoto.

Haruka train ticket from Kansai Airport
Haruka train ticket from Kansai Airport

In my journey I made a mistake of buying the one-way instead of the round-trip, thinking that I would take the Nankai railway back as many people suggest. Later I found out my hotel actually is closer to Tennoji (天王寺) where there is JR station, so at the end I took the JR Hanwa line rapid train to the airport, that costs 1060 JPY, and in total it is more expensive than the round-trip “ICOCA and Haruka” ticket set. So check the location of your hotel carefully, Google Maps is your friend.

The ticket set is sold on the 2nd floor of the JR office at Kansai airport, show them the passport when buying.

The railway system in Japan is complicated and could be astounding to new individual travelers, so
do your homework carefully in advance.

Travel in Kyoto

Kyoto is well connected with buses, they are very frequent and can reach all the popular attractions in the city. I took the bus almost exclusively in Kyoto, so I highly recommend buying the one-day bus pass. The pass costs 500 JPY and each bus ride costs 220 JPY, so the pass makes sense if you take more than 3 bus rides, not to mention you free your mind from worrying coins.

There are other passes that let you take subway as well, but since there are only two subway lines in Kyoto, I find bus to be more convenient and so subway passes may not be worth buying.

Travel in Nara

Deer in Nara Park
Deer in Nara Park

As Nara is not big and most attractions are close to each other, most people go to Nara as a day trip and stay in Osaka or Kyoto at night. For me, I stayed in Osaka and went to Nara in the morning by taking Kintetsu train to Nara Kintetsu station. Kintetsu has discount tickets called Nara-Ikaruga one-day pass (奈良・斑鳩1dayチケット) that offers unlimited bus rides in Nara and round-trip Kintetsu trains from/to Nara. Like Kyoto, you can go to many places just by bus so this ticket is highly recommended.

Nara-Ikaruga one-day pass (奈良・斑鳩1dayチケット)
Nara-Ikaruga one-day pass (奈良・斑鳩1dayチケット)

Depending on which city you buy the ticket, there are additional benefits. As I bought in Osaka, I could also enjoy unlimited rides on bus, subway and new tram in Osaka.

In Osaka, the ticket can be bought at the subway station supervisor office (駅長室), which is surprisingly located after passing the gate, which could be hard to find in maze-like Osaka subway stations.

Travel in Osaka

Osaka has a good subway system that covers most key destinations so getting a one-day pass is a smart choice.

The most basic form of the one-day pass is the Enjoy Eco card, which costs 800 JPY on week days and 600 JPY on weekends and national holidays. It can be bought directly from ticket machines. This card can be used on New Tram and bus as well, and offers discounts to some attractions like Osaka Castle and Floating Garden Observatory.

Enjoy Eco Card
Enjoy Eco Card

If you ever come across the Osaka Visitors’ Ticket and wonder what it is, forget it if you do not live in Hong Kong, Taiwan or Korea. It has the same benefits as the Enjoy Eco card, but with a lower price and is only sold in these 3 regions.

There are many other passes, such as Osaka Amazing Pass and Osaka Kaiyu Ticket, see which one suits you best here.

Money Matters

If you buy the “ICOCA and Haruka” ticket set, you will then have the ICOCA e-money card with 1500 JPY in it, which can be used to take trains and subways. But it is not too useful as a means in buying stuffs as many shops do not accept it, except convenient stores like 7-11. In Osaka, I found vending machines accepts PiTaPa rather than ICOCA as well.

Before leaving Japan, ICOCA can be returned at JR office and you can get 500 JPY deposit back. 220 JPY will be charged as handling fee from the remaining amount in your card, so if you have spent all the money in the card then it means no handling fee. If you think you will visit Kansai again in 10 years, you can keep the card and recharge it next time when you come back to Japan.

That’s it! Hope you enjoy Japan and find my tips useful.

where Open Source technology and Middle Kingdom meet