Posted by & filed under Internet, Linux.

I recently signed up for a free 50gb account at Box.net. At the time of this writing, Box.net does not have an application to sync files from a Linux machine to their servers. I followed this guide and this post to mount the service to a local directory. I did:

sudo apt-get install davfs2
emacs -q -nw /etc/davfs2/secrets
## added the following to the end of the file: "https://www.box.net/dav username password"
mkdir /mnt/box.net
## added the following to /etc/fstab
## following equivalent to defaults except noauto instead of auto; http://www.tuxfiles.org/linuxhelp/fstab.html
https://www.box.net/dav /mnt/box.net    davfs   rw,suid,dev,exec,noauto,nouser,async,uid=vinh,gid=vinh  0       0

Now do sudo mount /mnt/box.net to have have it mounted. Note that the account will automatically mount at startup.

Input/Ouput error

If you get an input/output error when copying files to your box.net folder, then add the following to your /etc/davfs2/davfs2.conf (per this post):

use_locks       0

Automount

I have the noauto option in /etc/fstab because I don’t want the box.net directory to be mounted at boot time. Why? Mounting requires an internet connection, and a network cable might not always be plugged; a mount error would require manual intervention (Skip or Manual mount) at startup. Instead, we should automatically mount the box.net directory whenever a network connection is made by placing the following script,

#! /bin/bash

mount /mnt/box.net

as /etc/network/if-up.d/mountBoxDotNet; remember to make it executable with chmod +x.

Posted by & filed under Internet.

I use my gmail account to manage multiple email accounts/addresses. I recently wanted to set up a vacation responder for one of my email address. However, the default vacation responder in gmail uses the default email account to send and there is no option to activate vacation responder for a single email address. I found this post on lifehacker that shows how one could set up a flexible auto response system with the use of a gmail account dedicated to auto response. Let gmail 1 be my primary account, and gmail 2 be my dedicated account. Basically,

  1. Add gmail 2 as a forwarding account in gmail 1.
  2. Set up a filter in gmail 1 that forwards to gmail 2.
  3. Add gmail 1 as an account in gmail 2 so that gmail 2 can send as gmail 1.
  4. Set up vacation responder in gmail 2.

Now, emails sent to gmail 1 that fits the condition of the forwarding filter (e.g., “to:work.address@my.company.com”). Remember to turn off the filter in gmail 1 and vacation responder in gmail 2 when the auto-response is no longer needed.

Posted by & filed under Linux.

The one thing that annoys me when I use screen is that I can’t scroll up after a long output has printed. To log outputs, add the following near the top (required!) of your screenrc file ($HOME/.screenrc):

# auto-log http://www.cmdln.org/2007/07/20/automatic-session-logging-and-monitoring-with-gnu-screen-for-the-paranoid/
## search for "STRING ESCAPES" in the manpage
# logfile /tmp/screen_%Y-%m-%d-%c:%s_%n.log
## not using above because every window gets its own time too.  rather use session name; need 4.01.00devel (GNU450e8f3) 2-May-06 and above
logfile /tmp/screen-%S-%n.log
deflog on

For example, my rc file now looks like:

escape ^Oo
# auto-log http://www.cmdln.org/2007/07/20/automatic-session-logging-and-monitoring-with-gnu-screen-for-the-paranoid/
## search for "STRING ESCAPES" in the manpage
# logfile /tmp/screen_%Y-%m-%d-%c:%s_%n.log
## not using above because every window gets its own time too.  rather use session name; need 4.01.00devel (GNU450e8f3) 2-May-06 and above
logfile /tmp/screen-%S-%n.log
deflog on
##escape \56\56 ##ascii octal http://www.robelle.com/library/smugbook/ascii.html http://www.ncsu.edu/it/mirror/ldp/LDP/LGNET/147/appaiah.html Use C-. for escape
## following for starting screen at 1 instead of 0
## http://www.linuxquestions.org/questions/linux-software-2/gnu-screen-start-window-numbering-at-1-keep-window-number-0-from-ever-being-used-772580/
bind c screen 1
bind 0 select 10
screen 1
select 1

When I originally had the log options at the bottom, logging did not work for me.

Finally, you can use the %S string escape to refer to the session name in screen 4.01.00devel (GNU450e8f3) 2-May-06 and after. It might be wise to install the git version of screen.

Compiling bleeding edge version of screen

sudo apt-get remove screen
git clone git://git.savannah.gnu.org/screen.git
cd screen
./mktar
tar xvf screen-*.tar.gz
cd screen*/
./autogen.sh
./configure
make
sudo make install

Posted by & filed under VoIP.

Asterisk is a very powerful open source telephony platform. I’ve described how to install it and configure Google Voice with it in the past. Setup is quite complicated for a newbie to get started. I was never able to set it up to the point for me to connect to the Asterisk server using the SIP protocol to make calls. Luckily, there is FreePBX which makes configuring Asterisk a lot easier. Even better, there are PBX in a Flash (PIAF) and Incredible PBX (choose different PIAF versions) ISO’s that make creating a PBX sandbox server quite easily. With these tools, I will be able to have my own conference call number and fax number for personal use.

Although PIAF is based on CentOS, a Linux I had zero experience with, the installation process was a breeze. I will describe my adventures based on this guide. At the time of this writing, PBX in a Flash 2 with CentOS 6 was just released, but I will stick with the version based on CentOS 5.7 as CentOS 6 requires more system resources and I am using the platform on an old P4 computer with 1 gig of ram.

Getting help

Before I outline any instructions, let note where you can get help. The best place to go is probably #freepbx on irc.freenode.com. It gets quiet sometimes, but just ask questions and be patient. Also, describe what you did to arrive at your current situation, and whatever advice they give you, just do it.

I also used the PIAF Help forum to get help, although I think more pro’s are over at #freepbx. However, new users cannot post immediately (will show as banned). I had to go through the hoops and contacted the forum owners through many channels to get myself the ability to post.

On the FreePBX admin page, mouse-over different categories on a page for a description of what the options are.

Installation

First, download the 32-bit PIAF as described here. I created a bootable USB flash drive from the ISO file (pbxinaflash-FlashDrive-17571.iso) using unetbootin. After booting up the flash drive, I selected to install PIAF-purple (long term support version). CentOS will then be installed. After it reboots, scripts will automatically install Asterisk, FreePBX, additional modules, and all necessary dependencies. Note that internet access is required for the installation process as files are downloaded and installed on the fly. After PIAF is installed, log in as root and issue:

cd /root
wget http://incrediblepbx.com/incrediblepbx2.x
chmod +x incrediblepbx2.x
./incrediblepbx2.x
/root/incrediblefax.sh
shutdown -r now

All necessary modules are now installed.

Security measures + remote sip connections

It is important to keep your system as secured as possible. Ideally, it should be sitting behind a firewall (hardware) with no ports exposed to the internet. That is, users connecting to the PBX server for phone service should be on the same local network as the server. If your server is exposed to the internet, at least take these precautions:

  1. Don’t allow root login for ssh. Use a different user for ssh access.
  2. Expose only the necessary ports. Don’t expose ports 80, 9080 (freepbx), and 9001 (webmin).
  3. Strong passwords for everything: root (also used for webmin), user, maint (freepbx web interface), and even the asterisk extensions.

To disallow root login via for ssh and create a new user for regular access, do

vi /etc/ssh/sshd_config
## Add: PermitRootLogin no ## change from yes to no
## create non-root user to login to ssh.  As root, do
useradd -d /home/newuser -m newuser
passwd newuser ## enter in password
## give newuser the power of sudo
vi /etc/sudoers
## add: newuser    ALL=(ALL)       ALL
## log out and login as newuser
## add to ~/.bashrc of newuser
export PATH=$PATH:/usr/kerberos/sbin:/usr/kerberos/bin/:/usr/local/sbin:/usr/sbin/:/sbin/

If you are behind a NAT firewall (router), forward these ports if they are relevant (remote sip connection):

SSH: 22 TDP/UDP
IAX: 4569 UDP; to connect to server via IAX protocol remotely
SIP: 5060 UDP; to connect to server via SIP protocol remotely
RTP: 10000-20000 UDP (/etc/asterisk/rtp.conf); voice connections
Don't open 80/9080 (freepbx administration) and 9001 (webmin)

For remote sip connection, I believe you also need to go to Tools (top of page) > Asterisk SIP Settings. Then modify the NAT settings: external IP and Local network (eg: 192.168.1.0/255.255.255.0). Click “Auto Configure” to automatically do this.

I originally had my server exposed to the world thinking the server is quite secure. I still think it’s pretty secure as Fail2ban and iptables work quite well; see this experience with trying to connect to a SIP extension from outside (remote connection) where the extension was restricted to only internal IP addresses. Basically, if you fail to authenticate any service (ssh, http, sip, etc.) a few times, the server will no longer respond to you (all services) until the pbx server is restarted.

My current setup: pbx behind a router with only the necessary ports opened as advised by all the experts.

One issue I encountered was that I was able to register a sip connection on the local network but not remotely across the internet, even though all my ports were forwarded. Using the following method, I realize that my connection to port 5060 never made it to the server:

asterisk -vvvvvr
sip set debug on ## debug sip registrations.  if you are trying to register a connection and you don't see any activity here, then your packets never made it to the server 

Even if I removed the firewall (router) and exposed all ports to the internet (DMZ), I was not able register a remote sip connection. I later realize it was because of iptables (Linux firewall) on the pbx server. See this for more details. After executing the following command,

iptables -A INPUT -p udp -m udp --dport 5060 -j ACCEPT

I was able to register a remote sip connection. To make this permanent, I added the rule via Webmin (http://local.ip:9001/). Your pbx server needs to respond to inquiries from ports 5060, 4569, and 10000-20000 UDP; I think somehow 5060 was set as TCP instead of UDP during installation, so I had to fix it manually. Restart the server to have the new rule take effect. Thank you n3glv, navaismo, adam1, and [TK]D-Fender from #freepbx for your help.

To guard against bots scanning for pbx servers, it might be wise to change the sip port for each extension from 5060 to something else.

Google Voice

Follow the instructions described here. Note: after submitting any changes, you need to click on the orange button on the top that says Apply Configuration Changes for it to take effect. Not doing this deferred my pbx installation by 2 months as I couldn’t get GV to work. I thought there was an issue with my setup even though I followed the guide step by step. It turned out to be this simple Apply Configuration Changes button at the top.

I set up 3 GV accounts: 1 as a phone account, 1 as a fax account, and one as a conference call account.

To help debug asterisk, as root, execute asterisk -vvvvvr to get into the command line interface. Some helpful commands:

jabber show connections ## see if gtalk accounts are connected
reload jabber

Set up extensions

Go to the extensions page in the FreePBX admin page. Pick an extension (e.g., 701). Change secret to a more secured password. Modify the deny and permit fields to restrict the IP address of devices/softphones connecting to this extension. If connecting from outside the network, you can leave both fields blank or enter in the appropriate IP address.

Assign a GV account (trunk) to be the default outbound route for an extension

This is a little tricky. Go to the “Outbound Routes” page. For outbound routes that you want an extension to always use, drag them up the list to the right. In the “Dial Patterns that will use this Route” section, add in the CallerId option (extension number) for whatever pattern you want; this is crucial for wanting an extension to use a single trunk. For example, you can put NXXNXXXXXX for the matched pattern field and 701 for the CallerId field. Now, whenever a 10 digit phone number is entered for extension 701, it will use that specific outbound route. Additionally, you can put NXXXXXX for the matched pattern field, 701 for the CallerId field, and your three digit area code for prepend for 7 digit dialing. Remember, for this to work, no outbound route above the current outbound route (right of page) should have any unrestricted dial pattern that matches the ones defined for the current outbound route.

Assign inbound calls of a DID to an extension

On the “Inbound Routes” page, add an incoming route with DID Number to be the phone number you want assigned to fax (e.g., a google voice number). Under “Set Destination”, choose Extensions and choose 701 (or another extension) to it’s side.

Make sure to Apply Configuration Changes after submitting.

Fax

On the “Inbound Routes” page, add an incoming route with DID Number to be the phone number you want assigned to fax (e.g., a google voice number). Under “Set Destination”, choose Custom Destinations and choose Fax (Hylafax) to it’s side.

Make sure to Apply Configuration Changes after submitting.

Conference Call

On “Conferences” page, fill in the fields “Conference Number” (anything), “Conference Name” (anything), “User PIN” (pin for all users to enter conference), and “Admin PIN” (pin for owner). Then choose your Conference Options; I set it to wait for leader.

On the “Inbound Routes” page, add an incoming route with DID Number to be the phone number you want assigned to fax (e.g., a google voice number). Under “Set Destination”, choose Conferences and choose the conference name you just set up previously.

Make sure to Apply Configuration Changes after submitting.

Restart

You need to restart asterisk (sudo amportal restart) or restart the computer (sudo shutdown -r now) for a lot of these settings to take effect.

Server not responding?

When you fail to connect (wrong password) to certain services (web, ssh, sip) about 3 times, Fail2Ban will kick in and not respond to you anymore. You have to restart the server for it to respond to you again.

Accessing FreePBX and Webmin web interfaces remotely

Since the web ports of the pbx server are not exposed to the internet, you can’t remotely access the web configuration pages. You also need to use the web interface to send faxes. To do so, you could either ssh into the server and use firefox (yum install firefox). Another possibility is to forward the necessary ports:

ssh -f -N -L 9080:localhost:9080 username@pbx.server
ssh -f -N -L 9001:localhost:9001 username@pbx.server

Now, on your local computer, you can type http://localhost:9080 to get to the FreePBX web interface.

Posted by & filed under Linux.

To shutdown in Ubuntu, I issue as root shutdown -P now. However, in CentOS, the computer does not shutdown and I get the message

Telling INIT to go to single user mode.
INIT: Going single use
INIT: Sending processes the TERM signal
INIT: Sending processes the KILL signal
sh-3.1#

The shell is active. Using Google I found this which states I need the -h (halt) argument whenever I want to power down. Don’t know why this wasn’t required on Ubuntu. To summarize, issue shutdown -P -h now in order to shutdown the computer.

Posted by & filed under Linux.

I automatically mount disk drives using /etc/fstab. However, when I boot a system with a disk removed, the system will give a mount error, giving me the option to skip (S) or manually (M) mount the disk. This doesn’t work well for headless servers. To skip the mount errors during boot, this suggests using the nobootwait option in /etc/fstab. Examples can be found here. For me, I have something like the following:

/dev/sdb1       /h2tb           ext3    defaults,nobootwait             1       2
/dev/sdc1       /wd2tb          ext4    defaults,nobootwait             1       2

Posted by & filed under Linux.

I’ve been searching for a way to save the output of the console when my Linux system boots up because

  1. I can’t spot errors fast enough at startup and
  2. I don’t notice errors on headless (no monitor) servers.

This shows a list of useful Linux log files, and I believe messages printed to the console at startup is stored in /var/log/boot.log. Don’t bother with bootlogd as described here as there are issues related to it.

To get these messages sent to your whenever the system reboots, one can use bootmail:

sudo apt-add-repository ppa:bootmail/ppa ## for ubuntu < 11.10
sudo apt-get update
sudo apt-get install bootmail ## enter in email address
sudo bootmail ## check

Make sure mail is set up for the root user.

Posted by & filed under Internet.

I use Google Docs to collect data using the Forms feature. People can just fill out the form and data will be automatically entered into a spreadsheet for me. It really makes data collection easy in simple cases. For example, creating a contact form using Google Docs is fairly straightforward. Google can even notify you when someone submits a form. However, the notification feature is weak in that it doesn’t provide any useful or customizable data; it just lets you know someone submitted a form. Luckily, Google has a scripts feature. This mail merge feature shows how you can email a list of people individualized emails. To get more useful notifications, you can write a script that will run whenever submits a script. This is a very useful example. I’ll reproduce it here:

var formSheet = SpreadsheetApp.getActiveSheet();
var firstRow = 2; //Skip a row for column labels
var lastForm = formSheet.getLastRow();
var lastCol = formSheet.getLastColumn();
var flagCol = null;
var subject = formSheet.getName() + " Form";
var mailTo = "";
var collaborators = SpreadsheetApp.getActiveSpreadsheet().getCollaborators();
for(var i=0; i < collaborators.length; i++){
mailTo += collaborators + ",";
}
var labels = formSheet.getRange(1, 1, 1, lastCol).getValues()[0]; //get column Labels

for(var i=0; i < labels.length; i++){ //Find which column contains the Sent Flag
if(labels[i] == "Email Notice Sent"){
flagCol = i;
break;
}
}
if(flagCol === null){//Sent Flag Col not found, create it
formSheet.insertColumnsAfter(lastCol++, 1);
formSheet.getRange(1, 1, 1, lastCol).getCell(1, lastCol).setValue("Email Notice Sent");
SpreadsheetApp.flush();
flagCol = lastCol;
}

for(var i = lastForm; i >= firstRow; i--) { //Loop through forms, last first
var form = formSheet.getRange(i, 1, 1, lastCol);
var formVals = form.getValues()[0];

var message = "";
var html = "";

if(formVals[0] != "" && formVals[flagCol] != true){ //Skip empty and email sent rows
for(var col=0; col < lastCol; col++) { //Build the message
if(col != flagCol){
message += labels[col] + ": " + formVals[col] + "nn";
html += "

" + labels[col] + ":"

htmlVal = formVals[col].toString().replace(//g, ">").replace(/[rn]/g, "
");
if(typeof(formVals[col]) == "string" && formVals[col].length > 100){
html += "

" + htmlVal + "

";
}
else {
html += htmlVal + "

";
}
}
}

GmailApp.sendEmail(mailTo, subject + ": " + formVals[1], message, {"htmlBody": html});
form.getCell(1, flagCol+1).setValue(true);
SpreadsheetApp.flush(); // Make sure the cell is updated right away in case the script is interrupted
}
}

The syntax is fairly obvious if you ever programmed before. I successfully modified the script for my own use.

Posted by & filed under Internet.

WordPress is no doubt a great blogging platform. However, it is also a user-friendly Content Manangement System (CMS) that can be used to run a website. However, you have to tweak it to not look like a blog and more like a traditional website. The easiest way to do so is probably through an appropriate theme. I ran into the Phanatics theme, which looks very asthetically appealing with a monetary fee for its license. I also found the free Weaver theme to also be good looking.

For basic sites that I don’t want to host, I’ll probably still be using Google Sites. For sites that I want more control over and be able to host, I’ll rely on WordPress with an appropriate theme.

Posted by & filed under Internet.

I recently changed my WordPress theme to Reflex+, a theme that resembles the current look of Google+ and other Google related services. I had to make some manual modifications.

Excerpt vs. full content for each post

On the main index page, you can either show just an excerpt or the full content of each post. I like the full content. To get the index page of your current theme to show the entire content of each post, find a line in ./blog/wp-content/themes/reflex-plus/index.php similar to

#+END_EXAMPLE



and change it to



#+BEGIN_EXAMPLE

My changes:

»').''); */ /*vinh: display full content instead of summary */?>
»').''); ?>

Edit link style

I don’t like it when links are not visually different than normal text. I followed this post and modified ./blog/wp-content/themes/reflex-plus/style.css:

div.post a:link {
color: #09C;
}

div.post a:visited {
color: #006;
text-decoration: none;
}

Adding instructions or comments to the comments section

I wanted to give instructions on writing Markdown Syntax, source code, and LaTeX near the comments box. I modified ./blog/wp-includes/comment-template.php as follow:

/* 'comment_notes_after' => '

' . sprintf( __( 'You may use these HTML tags and attributes: %s' ), ' =' . allowed_tags() . '=' ) . '

', */ /* vinh */
'comment_notes_after' => '

Use [[http://daringfireball.net/projects/markdown/syntax][Markdown Syntax]] for markup.
Surround blocks of code with 
 and 

. For syntax highlighting of specific languages, use the appropriate "brush alias" from [[http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/][this]] list. For example, surround php code with

 and 

.
LaTeX code can be surrounded by "backslash left parenthesis" and "backslash right parenthesis" or "backslash left square bracket" and "backslash right square bracket".

',