Tag: tutorial (page 1 of 3)

React Native URL Scheme and Linking API

React Native is possible the best hybrid framework for building mobile app at the moment. Not just its performance but also the development experience it provides. If you build it well, one really can’t tell if your app is native or a hybrid.

I spent my last 3 month developing a complicated hybrid app using react native. It involves many network requests, forms, lists, etc. It was undoubtedly challenging, but the result was quite satisfying.

For my next project, I was given another chance to work with React Native. This time I need to build a “AppStore” kind of application, which allow the user to install apps and launch installed apps right from this custom “AppStore”.

To launch other Apps in iOS or Android, we must register custom URL Schemes in the Apps we wish to launch.

Register URL Schemes

iOS

On iOS, we need to add a key CFBundleURLTYpes to the Info.plist file within the Xcode project.

Under this key we add an array, and define 2 keys CFBundleURLName and CFBundleURLSchemes.

Under CFBundleURLName you need to add a unique string that identifies your bundle, I used the same string as my app’s bundle identifier and it worked fine. Under CFBundleURLSchemes you need to add another array, and put in your desired URL schemes.

Here is an example of such entry inside Info.plist:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>com.johnsonsu.example</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>johnsonsu-example</string>
        </array>
    </dict>
</array>

More info about iOS URL Scheme can be found on the official documentation.

Android

Android’s setup is similar to iOS. We need to add a custom intent-filter in the Android app’s AndroidManifest.xml file.

Here is an example of such intent-filter:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT"/>
    <category android:name="android.intent.category.BROWSABLE"/>
    <data android:scheme="johnsonsu-example"/>
</intent-filter>

Since React Native’s Linking API will be creating an intent with action equals to android.intent.action.VIEW, your intent-filter must contain an action tag with this name.

The data tag is where you should define your custom URL Scheme. In this example I used the same one as the iOS scheme. Doing it this way allows me to use the exact same code in React Native to launch these applications in both iOS and Android.

More info about Android Intent Filter can be found on the official documentation.

Launching the App in React Native

If you setup your apps properly, you should be able to launch that app in React Native using:

import { Linking } from 'react-native';

Linking.openURL('johnsonsu-example://').catch(err => console.error('An error occurred', err));

If the OS can’t handle the URL you tried to open, the exception will be caught inside the catch block, and you should handle it properly to prevent a crash.

A safer way to open URL is to check if the OS can handle it before you open it. You can check it using:

import { Linking } from 'react-native';

const url = 'johnsonsu-example://';
Linking.canOpenURL(url).then(supported => {
  if (!supported) {
    console.log('Can\'t handle url: ' + url);
  } else {
    return Linking.openURL(url);
  }
}).catch(err => console.error('An error occurred', err));

This works on Android without any setup. However, on iOS 9 or above, you need to add LSApplicationQueriesSchemes to your React Native app’s Info.plist or Linking.canOpenURL(url) will always returns false.

This is an example entry in Info.plist:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>johnsonsu-example</string>
    <string>youtube</string>
    <string>facebook</string>
</array>

There you have it, a simple way to launch any other apps from your React Native app!

WordPress xmlrpc.php attack

Recently, one of my WordPress website has been attacked by thousands of request to the xmlrpc.php file. The attacks came from multiple ip address. Here is my apache access log(/var/apache2/access.log):

62.141.35.242 - - [15/May/2016:21:05:38 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
188.120.41.8 - - [15/May/2016:21:05:44 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
62.141.35.242 - - [15/May/2016:21:05:39 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
188.120.41.8 - - [15/May/2016:21:05:54 +0800] "POST /xmlrpc.php HTTP/1.1" 200 0 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
188.120.41.8 - - [15/May/2016:21:05:35 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
62.141.35.242 - - [15/May/2016:21:05:39 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
62.141.35.242 - - [15/May/2016:21:05:41 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
62.141.35.242 - - [15/May/2016:21:05:37 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
62.141.35.242 - - [15/May/2016:21:05:39 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
62.141.35.242 - - [15/May/2016:21:05:43 +0800] "POST /xmlrpc.php HTTP/1.1" 200 620 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"

These attacks come and go, and they had took down my site several times over the last few months. I did some google and found out that this kind of attack has been around for a while. It attempts to use the xmlrpc.php file to brute force WordPress logins.

Solution

Block IPs with ufw

Most ubuntu server has ufw installed, it can be used to block specific ip address from accessing the server.

I run the following command(reference) to get a list of attacker’s ip addresses:

$ grep xmlrpc /var/log/apache2/access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn | head

// results
6039 62.141.35.242
1566 154.16.63.40
1411 188.120.41.8
 248 195.2.252.132

Those numbers in front of IPs are the number of times each ip requested the xmlrpc.php file.

Then for each of the IP address, I used the following command to block them using ufw:

sudo ufw deny from 62.141.35.242 // replace with your attacker's ip address

I then ran the list attacker command a few more times after I blocked all IPs. Unfortunately, the access count is still increasing. There seems to be a problem with iptables on Ubuntu, but I couldn’t find a solution. So I tried another method to deal with these attacks.

Modifying Apache Virtual Host Config

Which is adding the following:

<VirtualHost>
…    
    <files xmlrpc.php>
      order allow,deny
      deny from all
    </files>
</VirtualHost>

to your WordPress apache virtual host config file.
My config file is the standard

/etc/apache2/sites-available/000-default.conf

Modifying this file will not block the attacker’s request, but reduce the amount of resources the request consumes on your server.

After I reload the apache with

sudo services apache2 restart

I was able to access my WordPress website again.

How to setup Apache Virtual Host on Ubuntu 14.04

These days setting up a website is easy. We can simply buy a domain, get a web host or cloud service, put up a WordPress or other platforms, done. There are tons of tutorials on the internet, and I just happen to have one as well.

Often, after that initial setup, you might realize that you are not utilizing all the computing power of the cloud and the capabilities of your domain. You are not getting that many traffics on your website. In fact, for most of the time your server just sits there, not serving anyone. On the other hand, other than www.example.com, you are not using any of the unlimited subdomains like whatever.example.com that happens to come with your purchase of the example.com.

Now that you realize the potentials of what you already own, you can utilize them. One way to do that is setup another personal blog for yourself or a photo gallery for you and your love ones (There is only 1 love.example.com!). However, doing such thing often requires the use of virtual host or vhost for short. You don’t know how? I am here to help!

What is Virtual Host

host helps you to host website, or several websites on the same computer. I use it to host johnsonsu.com and blog.johnsonsu.com on the same AWS EC2 instance.

Apache vhost Setup for Ubuntu 14.04

Apache comes with vhost by default. In fact, apache is using vhost to host your current website. In Ubuntu 14.04, apache’s vhost related files are located in:

    /etc/apache2/site-available/

Inside this directory, you should see a 000-default.conf file. This is the default configuration file for apache vhost. The content should look something like this (with out the comments):

    <VirtualHost *:80>

        ServerAdmin [email protected]
        DocumentRoot /var/www

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

    </VirtualHost>

What this does is when someone connects to your server on port 80 (default port for HTTP), apache will handle that request with the things in side /var/www, which is usually your website’s root folder.

Now, we want to host more website on the server, say we a www.example.com and a blog.example.com. To save the hassle, we can simply duplicate the default configuration. We can run the command:

    sudo cp /etc/apache2/site-availabel/000-default.conf www.example.conf     #copy the default config file to a new file called www.example.conf
    sudo cp /etc/apache2/site-available/000-default.conf blog.example.conf     #copy the default config file to another new file called blog.example.conf

Now we have 2 new config file, let’s edit them. We want the www.example.conf to look something like this:

    <VirtualHost *:80>

        ServerAdmin [email protected]
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/wordpress  #You should change this to your main site's root folder

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

    </VirtualHost>

Whereas blog.example.conf should look like this:

    <VirtualHost *:80>

        ServerAdmin [email protected]le.com
        ServerName blog.johnsonsu.com
        DocumentRoot /var/www/blog  #You should change this to your main site's root folder

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

    </VirtualHost>

Notice they are very similar. The only thing you need to make sure is the ServerName and DocumentRoot are correct.

Now you can go to your domain’s DNS manager. For example, if you purchased domain from godaddy, then go to godaddy.com, login, and edit your DNS. You would want to add a new CNAME record with name blog as an alias of example.com and point to the same server IP address. After that save the changes and wait for DNS to update, this can take a while.

Now if you go to blog.example.com, you should see whatever you put in /var/www/blog. Congratulations, you now have another website on your server, without paying any extra!

You can easily create a bunch of WordPress website for your hobby(guitar.example.com), your lover(love.example.com), your family members(family.example.com), even for your dog(you got it!).