Udi Mosayev

Vegan, Athlete, Developer

How To: Reverse SSH Tunnel

Intro

You ever had to access a server/computer behind a firewall / closed network? your office computer or perhaps one of your servers behind a closed network/firewall.

For one of my contract projects I had to have a full control over a server in a remote location inside a closed network. In order to do that I had to setup a reverse ssh tunnel.

(This post is written for Ubuntu and OpenSSH)

You need

A Server behind closed network, lets call it “remote server”.
A proxy server. A server you can access easily which you’ll use in order to SSH into the remote server.

Step 1: Configure OpenSSH

Open /etc/ssh/sshd_config

1
$ vi /etc/ssh/sshd_config

Find GatewayPorts and make sure it says ‘yes’. If it doesn’t exists, add it:

1
GatewayPorts yes

Save & close.

Run:

1
$ service ssh restart

Repeat the same process on OpenSSH of the remote server as well.

Step 2: Open the Tunnel & Connect

In your remote server, run:

1
$ ssh -t -t -R <tunnel_port>:localhost:22 proxy_server_user@proxy_server_ip

tunnel_port – can be any available port.
proxy_server_user – root or any other user you’ll have for that purpose.

Now the tunnel is open in our remote destination server, let’s connect to it through the proxy server.
First you need to ssh into the proxy server, then:

1
$ ssh user_on_remote_server@localhost -p <tunnel_port>

This is it.

If the remote server is an office computer or something you can access daily, you’ll probably open this tunnel before you leave the office. Otherwise, you need to figure out a way to do it remotely, when you don’t have physical access to that machine (read the Automating Tunnel Management below).

Authentication

Every time you’ll create the tunnel, it’ll ask you for password/passphrase and etc. In my case, the tunnel is created by me for the first time, but afterwards I need to create it remotely by scripts, and I couldn’t have password/passphrase in the process. So this is what I did:

1. Create a tunnel user on proxy server.

2. Create an SSH Key on remote server (empty passphrase, so it won’t ask for it), add this key to /home/tunnel/.ssh/authorized_keys file.

Automating Tunnel Management

In my case, the server sits in a corner of a room, without any monitor or keyboard. No one can easily access it without a laptop connected to the same network this server is connected to.
Whenever I need to create a tunnel, I want to be able to click on a button on my machine and make the remote server create the tunnel on a port I define. For this reason I’ve created a cron job that runs every minute, it pings my server and asks “Hey, I’m server 163, do you need me to do anything?”
In this point I send back a JSON describing what I need this script to do. It can be anything: update the code, run OS update or open an ssh tunnel on port X and proxy server Y.

Hope it helps. I’m not a sysadmin guru, but I’ll be glad to help if you have any questions.

Updated MY_Model class for CodeIgniter 2.0

Hi,

A year~ ago I shared with you MY_Model class I wrote and used on most of my CodeIgniter projects, since these posts are still popular but very very old I’ve decide to share the most recent one, which I host on GitHub as well, It’s still in progress, but gives you a solid start with your own projects.

Link to the Gist.

Creating Applications with AppIgnite

A few months ago, I had the opportunity to test AppIgnite.  Now, I want to share my Applgnite experience with you.

What Is AppIgnite?

AppIgnite is a web application that allows anybody with minimal technical knowledge to create web applications. If you know how to work with MS Excel, you can easily produce useful applications with AppIgnite in no time.
AppIgnite was developed by Jason Roberts, a freelance coder and the co-host of TechZing, a great tech podcast which I’ve mentioned in the past.
My first application in AppIgnite was an application for managing personal finance, which I have used to track my expenses/income from different categories.
*Please note: Some Javascript coding and views modifications was needed to actually show “total expenses” on the page. More on that later.

The way it works:

When creating a new application, you can create models. In my application, I have a default “User Model” (which is responsible for user and permissions management in your app and is part of the basic skeleton for each AppIgnite application), “Entry Model” (which represents each expense/income) and “Categories Model.”

You can easily define properties for each model and even define relationships between the different models (for example, the “Entry Model” has 1 category).  You can also set permissions for each model (from the built-in user/permissions management) and you can set the permissions for different CRUD functions within the same model.

Each model has “Views.” Views are the HTML templates for different screens in the application: New Entry form, Entries List table, etc.
AppIgnite has a built-in editor for the views. If you have technical knowledge, you can modify the HTML the way you’d like.

The bad news is that if you really want to change the layout of your app, it is a lot of work. You need to modify each new form individually and on top of that, when creating new models, their views will have the default layout. However, AppIgnite is still in development and I’m sure this feature will be a lot better once it’s final version is released. I hope that it will have the native CSS editor – I’m currently loading external CSS file for my app.  I also hope that it will  load jQuey (the more technical users can add some javascript awesomeness to their apps).

It has Version Control!

Well, not exactly. But it’s good enough. I believe Jason tried to keep AppIgnite as simple as possible for non-technical people to use it.  That way, if you’ve made a mistake or accidently changed something, and you’d like to revert it, you can go back to the previous “build.”

Each change you make creates a new build (i.e. another version of your application).  That way, when it breaks loose or you decide that you don’t like some of the latest changes, you can easily restore it to any of the past versions.

Exporting your application

This is one of the best features both business-wise and technically speaking.  AppIgnite allows you to export the application you’ve created and keep on developing it.

When exporting the application, you’re getting all of the code (PHP) and database (MySQL) from your app.  Even more, you get an install script. Then, all you have to do is upload it to your server and run the installation script.

Whom is it for?

This application is built so well, that it is suitable for all different levels of technical expertise and therefore has a ton of potential.

Let’s start with businesses that are both big and small.  Not everyone has a huge ERP system that manages every little detail in the company. Many employees work with shared Excel documents which aren’t necessarily enough.  It’s very costly for both your time and money to have custom software developed for that usage.  Therefore, a solution like AppIgnite comes in handy.  The coolest part is that AppIgnite is simple enough for employees to quickly create an application to manage the data they want.

Start-ups can speed up the development time of MVP or POC by creating an application with AppIgnite – exporting it and making all of the changes they want, right there, in the code. It’s even possible for them to use it for developing the final product!

Freelancers can use AppIgnite to generate a skeleton of their project, export the application, and keep developing the project.  It’s a big time saver.

If you want to hear more about AppIgnite, you can follow Jason Roberts and listen to his podcast TechZing.

Book Review: PHP 5 Social Networking

PHP 5 Social Network

PHP 5 Social Network

 

Honestly, I think they should rename this book.  Yes, it allows you to learn how to create a “social network” (ie. users, profilers, events, status stream). But it also gives you a lot more programming information than what you might expect. I hope that the people who are trying to learn PHP aren’t too mislead by the title to end up missing out on this book.
For example, in the first chapter, you are getting familiar with MVC and 3 other design patterns.

The biggest surprise in the book is in Chapter 13 – Marketing, SEO, User Retention, and Monetization Strategies.  A lot of people may already be familiar with the marketing and seo sections, but the user retention part in this chapter really caught my attention. It discusses how to keep users coming back. What is especially great about this chapter is that the strategies offered fit most websites/web applications.

 The closing chapter is Chapter 14 – Planning for Growth. I agree that one shouldn’t worry about scaling while building the product (you can also find this tip in other books). It’s more important to keep in mind the potential to be faced with decisions that can affect you in the long-run and are expensive to change.
In this chapter, the author also writes about code and server performance, scaling, caching, NoSQL and more.
There is no in-depth information about those subjects, but there is still more than enough information to get you thinking and allow you to know what to look for when the subject arises. The chapter gives you information about tools you should be familiar with, even if you don’t deal with any issues at the moment.

In conclusion, the chapters are really clear and well-structured.  It provides a step-by-step guide on how to create a social network.
After each chapter, you will get closer and closer to a decent social networking site.

Packt Pub book page

MY_Model v2.0 For CodeIgniter

Update: This post is very old. I’ve created new model class for my CodeIgniter projects, you can find it here: Updated MY_Model for CodeIgniter 2.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?php

class MY_Model extends CI_Model
{

    // The main table name
    private $_table;

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Setter/Getters for the table prop
     * @param String $table
     */

    public function setTable($table)
    {
        $this->_table = $table;
    }

    public function getTable()
    {
        return $this->_table;
    }


    // Log as Error each time nonexisting method called.
    public function __call($name, $arguments)
    {
        $args = implode(',', $arguments);
        log_message('error', $name . '(' . $args . ') Not exists.');
        return FALSE;
    }

    /**
     * Checks if certain field in any row has a certain value.
     * Its used to have a unique data like username, email etc.
     * @param String $field Name of the field in the table to check the data in
     * @param String $value The value to check if exists in that field
     * @return Bool TRUE if this data exists, FALSE if unique
     */

    public function is_duplicate($fieldName, $value)
    {
        if (empty($fieldName) OR empty($value))
        {
            log_message('error', 'Got some empty param. field: ' . $fieldName . ' | value: ' . $value);
            exit(0);
        }
        else
        {
            $this->db->select($fieldName);
            $query = $this->db->get_where($this->getTable() , array(
                $fieldName => $value
            ));
            if ($query->num_rows > 0)
            {
                return TRUE;
            }
            else
            {
                return FALSE;
            }
        }

        return FALSE;
    }

    /**
     * This method inserts some array of data into the db
     * @param Array $data
     * @return Int Insert ID
     */

    public function add($data)
    {
        if (is_array($data))
        {

            // $data['Reorder'] = $this->getLastOrder()+1;

            $this->db->insert($this->getTable() , $data);
            return $this->db->insert_id();
        }
        else
        {
            log_message('error', 'Got non-array param.');
            return FALSE;
        }
    }

    /**
     * This method updates fields in my table.
     * @param String $fieldName
     * @param String $value
     * @param Integer $id
     */

    public function update_field($fieldName, $fieldValue, $id)
    {
        if (empty($fieldName))
        {
            log_message('error', 'Got empty fieldName: ' . $fieldName);
            return FALSE;
        }
        else
        if (!is_numeric($id))
        {
            log_message('error', 'Got non-numeric id: ' . $id);
            return FALSE;
        }
        else
        {
            $this->db->where('id', $id);
            $query = $this->db->update($this->getTable() , array(
                $fieldName => $fieldValue
            ));
        }
    }

    /**
     * Updates whole row [unlike update_field()]
     * @param Array $data
     * @param Integer $id
     */

    public function update($data, $id)
    {
        if (!is_array($data))
        {
            log_message('error', 'Supposed to get an array!');
            return FALSE;
        }
        else
        if (!is_numeric($id))
        {
            log_message('error', 'Got non-numeric id: ' . $id);
            return FALSE;
        }
        else
        {
            /* write the old&amp;new data to history
            foreach($data as $fieldName=>$fieldValue) {
            $this->history->write($this->getTable(), $id, $fieldName, $fieldValue);
            }

            */

            $this->db->where('id', $id);
            $this->db->update($this->getTable() , $data);
        }
    }

    /**
     * This method returns all the rows of this model
     * @param Array $where Array of field=>value
     * @param Array $orderby field to order by and side - desc/asc.
     * @return CI_Query_Resource the $query object
     */

    public function get_where($where = array('is_deleted' => 0) , $orderBy = null)
    {
        if ($orderBy != null) $this->db->order_by($orderBy[1], $orderBy[2]);
        $query = $this->db->get_where($this->getTable() , $where);
        return $query;
    }

    /**
     * This method gets 1 row from a table and returns it.
     * @param Integer $id
     * @return DB_Res $query CodeIgniter's db resource
     */

    public function get($id)
    {
        if (!is_numeric($id))
        {
            log_message('error', 'Got not numeric id: ' . $id);
            return FALSE;
        }
        else
        {
            $query = $this->db->get_where($this->getTable() , array(
                'id' => $id
            ));
            return $query;
        }
    }

    /**
     * This method logically deletes a row.
     * @param Integer $id
     * @return Boolean
     */

    public function delete($id)
    {
        if (is_numeric($id))
        {
            $this->update_field('is_deleted', 1, $id);
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
}

Start A Design Firm? A How to Guide By Forrst Users

I want to share with you a question by @garrettbolin on ForrstStart A Design Firm? A How to Guide By Forrst Users [Click to read the question].


You probably know I’m  a little bit experienced in this field, and I read the question during my morning tea so I was really focused and responded informatively.
Lots of people [ok ok.. only 22] found my comment useful, and I want to share it with you:

At the beginning

  • If you figure out you need a little bit of money to start, for legal docs and maybe some hardware [printer and etc.] then put this money in, but save it as much as possible. Buy used hardware, nothing fancy. Don’t buy “work” laptop, just use w/e you all have now.
  • Set a goal – set a goal, “We need to make $1k each month for the first 6 months. How can we achieve that?” think about your rate for all sorts of different work you can do, and establish a number of projects you need to do each month.
    This is your goal now, to have a number of project you must have and working your ass off to get them.
    The thing that helped me when I freelanced is to know “I need to sell my CMS app to 3 clients at least,
    if I’ll get a new app dev project, then I can afford myself to find only 1 buyer”. Setting a goal in business is very important rule.
  • Responsibilities – Who’s doing what. Sit down with your co’s, and define who’s doing what. You don’t want any issues to be forgotten because no one was responsible.

Clients, where are you??
These are some of the things I’ve done to find new clients:

  • Contacts – finding business owners through friends and family. Talk to everybody, “Hi man, your dad still has this bakery?”. EVEN IF this business owner don’t need your service [already has a website], try to figure out how the website helps his business, see why he wanted/needed a website from the begin with.
  • Hunt – Now, when you know why business X needs a website, write these things down in a nice document. Actually describe why a bakery needs a website and why, include good info like 30% more profit, 70% of the clients order online or using the cupons we have online when calling to order…etc.
    Meet other bakery owners in your town, give them a 5min pitch, explain why you think they need a website OR why the current one isn’t enough. Leave them the document for further reading, and wait for the call 🙂

Some quick tips:

  • Do more then promised – always do more then you’ve promised, but be careful with that. Read this post: Pride vs Payment http://forrst.com/posts/Pride_vs_Payment-BtL , its a very delicate issue, so if you need further explanation just ask.
  • Don’t lie/cheat/deceive – if a someone interested in a service, he probably talked to other firms/freelancers, or will be. Especially if its the first time you’re talking. So don’t lie or cheat. It might work for you once, but plz don’t do it. Be honest! if you don’t have an answer on a certain topic, just say so. Don’t treat them as one night stand, because if you’re good to them, they’ll be good to you and even refer people to you.
    You may earned few bucks from this client, but if he treated well, you’ll get through him or by him in the future lots of work. Trust me.
  • Work hard, life ain’t easy, and probably you’ll have hard time to achieve your goals and find new clients. But if you’ll work really hard, you see its worth it.
  • This is it.
    If this topic interests you, you can read How to become a freelance web developer – Part 1 I wrote.

    Book Review: “Pro PHP Refactoring” by Francesco Trucchia and Jacopo Romei

    Pro PHP Refactoring” written by Francesco Trucchia and Jacopo Romei, published by Apress.
    This book is for beginners and professional web developers.

    I never read a book about refactoring, maybe few chapters or articles here and there, but I never learned this subject. To me it was always just doing what feels right, I never thought about “what technic should I use here…”. If you are like me, and you feel that this book can’t really teach you something, you better take a look at the table of contents [Google Preview in Apress], I’m sure you’ll find few interesting chapters there.

    My favorite chapter is Chapter 1 – Finding “Bad Smells” In Code – they explain really well and clearly how to recognize bad code. Now, I don’t even wait for the second-look on a code, while I write I’m starting to feel where I did it wrong and where should I make some changes. This chapters helps you code better. Not only refactor better.

    In this book you’ll see and read a lot about unit testing in PHP with PHPUnit and what is TDD and why you need it. You’ll also get familiar with Selenium which is quite useful tool for web app testing [and from now on I’m using it as one of my testing tools].

    In conclusion,
    reading this book will help you not only refactor other’s code, but write your much better. You’ll learn about test driven design and testing in general. All of those will help you become much better developer.

    Podcasts and sites I’m following

    Hi,

    recently I unsubscribed from every feed in Google Reader, because I’m not using it anymore, and wanted to make sure I’m following all the sources on Twitter.
    So I found everything I’m interested in on Twitter and created @udiudi/articles.

    These are some of the interesting ones I want to share with you:

    Justin Vincent
    – There are 2 main reasons I’m following this guy, the first one is Techzing, his tech podcast [which I’ll talk about here] and I find the most interesting tweets in my stream from him [mostly some techy articles]. Also He is the developer of Pluggio, a premium twitter client.

    Techzing – Very interesting Tech podcast. It has everything I find interesting: Programming, Startup life, Tech news and 2 experienced hosts shares their knowledge with us.

    DeveloperWorks – One of my biggest sources of  professional content about the software development industry. I believe you won’t find to much of the subject they write about some where else.

    SitePoint.com [twitter] – SitePoint is a great source of web development related articles. Also, they write a lot about freelancing and even have several book about the subject. This site was extremely helpful for me when I began to code professionally.

    Nettuts – Like SitePoint, but much younger website, also is a great source of web development content. I love it that they mostly have screencasts, which is much better then written article in my opinion.

    Mashable – My main source of what’s happening in the tech industry.

    I rarely visit those sites, I’m sending a link of the article to my Instapaper account and reading it later.

    How to Become a Freelance Web Developer – Part 1

    Hi,
    Before I begin this post, I would like to make clear that I don’t consider myself to be a superstar web developer or a very experienced freelancer. However, I do have 4 years of freelance experience behind my belt and all of the tips and opinions are based on my past experience.
    Most of the freelance work I’ve done was web development which basically included building a website OR web application for various customers.
    In these articles I will talk about the different stages of project life cycle, the problems you might face, and how to deal with them.
    This part of the post series is about the pitching process and the quote, which are the start of each a project.
    Now, let’s get started…

    The Well Known Model of Freelance Project

    Project life cycle

    The Pitch and Quote

    The most important factor in pitching successfully, is preparation. You must learn your prospective customers business. Why?  Because in most cases, your main goal is to help them make more money.  It can occur through creating a website for their business, an improvement to their current website (for example, adding a shopping cart), or perhaps developing an application to save them time on different work flows.  All of these methods are eventually supposed to make money and/or save money for your customer.  So, naturally you need to know what you are dealing with.
    The way I usually prepare myself is by learning about the business from every possible source/angle.  If I want to pitch a new restaurant, I learn about the business. I look at websites of current successful restaurants and usually contact someone from the industry to get informed. What I look for:

    1. Problems – What problems do they have running their business? If we are talking about a restaurant that already has a website, what is wrong with it?  No online order system? Perhaps they don’t have a photo gallery of their best dishes on the menu. Is the owner able to manage his waiters’ shifts in an efficient manner?
    2. Bottlenecks – What’s the longest process in the business?  What’s draining a lot of hours? And how can you help them save time?
    3. Money-makers – This one is quite easy. However, sometimes it is difficult to “sell” this idea to the customer. For example, shipping!
    4. If, for some reason, the restaurant doesn’t have a shipping service, the idea of an “online order” might be difficult for your prospective customer to swallow. Your prospective customers may worry about the hassle of organizing a shipping service. So, it may be beneficial for you to suggest the idea, but don’t push it.

    After solid preparation, you can meet with your prospective client.
    My number one rule for the meeting: Don’t behave like a salesperson. Be Honest!
    It’s just like with girls. if you approach a hot babe at a bar, you both know what the intention is. There is no reason to mask your intentions with a fake facade. My point is, be honest and don’t try to get as much money as possible by being dishonest.  And this is true for the whole process, not just the pitching part.  If for even one second your client feels that you are not honest with him, you might lose him (and you will certainly lose any potential friend referrals from him/her).

    During the meeting, talk about the research you’ve done. Ask him how they deal with problem X and how much time it takes for them to finish Y (some bottleneck you discovered]) You can even plant a small seed, subtly suggesting a money-maker you thought about (but don’t overdo it). And of course, talk about your solutions and be as informative as possible during this time. If you did your homework and you are as prepared as you can possibly be, you’ll have more than enough reasons to show him why he should hire you for your services.

    The Quotation Document

    Don’t be too fancy-shmancy, unless the project is really big. The quotation document should not be more than 1.5 pages.
    If you’re working on an hourly basis, and the client agrees, then the paragraph below isn’t for you.
    You should describe the services you are going to supply as different subjects, describing each one in a sentence or two and including the price next to it.
    I don’t like to write a bunch of “I’ll do this” and the total price for the job, I prefer describing each item individually.

    That’s all for this part of the series. In my next post I will write about the actual work process, the problems you might encounter, and the best way to deal with them.
    Hope you enjoyed this and feel free to ask questions by posting a comment.

    Much cleaner and basic MY_Model for CodeIgniter

    Update: This post is very old. I’ve created new model class for my CodeIgniter projects, you can find it here: Updated MY_Model for CodeIgniter 2.0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    class MY_Model extends Model {

    /**
    * The table name of this db table
    * @var String
    */

    private $_table;

    public function __construct() {
    parent::Model();
    }

    public function setTable($table) {
    $this-&gt;_table = $table;
    }

    /**
    * This method inserts some array of data into the db
    * @param Array $data
    * @return Int Insert ID
    */

    public function add($data) {
    if(is_array($data)) {
    $this-&gt;db-&gt;insert($this-&gt;table, $data);
    return $this-&gt;db-&gt;insert_id();
    } else {
    $this-&gt;log('error', 'Got non-array param.', __METHOD__);
    return FALSE;
    }
    }

    /**
    * Updates row with the data array given
    * @param $data
    * @param $where Mixed Array
    */

    public function update($data, $where) {
    if(!is_array($data)) {
    $this-&gt;log('error', 'Supposed to get an array!', __METHOD__);
    return FALSE;
    } else {
    /*
    // write the old&amp;new data to history
    foreach($RowData as $fieldName=&gt;$fieldValue) {
    $this-&gt;history-&gt;write($this-&gt;table, $RowID, $fieldName, $fieldValue);
    }
    */

    foreach ($where as $field =&gt; $value) {
    $this-&gt;db-&gt;where($field, $value);
    }

    $this-&gt;db-&gt;update($this-&gt;_table, $data);
    }
    }

    /**
    * This method logically deletes a row.
    * @param Integer $rowID
    * @return Boolean
    */

    public function delete($rowID) {
    if(is_numeric($rowID)) {
    $this-&gt;updateField('IsDeleted', 1, $rowID);
    return TRUE;
    } else {
    return FALSE;
    }
    }

    /**
    * Logs an error
    * @param String $level
    * @param String $msg
    */

    final protected function log($level, $msg, $method=__METHOD__) {
    log_message($level, $method.' :: '.$msg.' [In: '.__FILE__.' Line: '.__LINE__.']');
    }

    public function __call($name, $arguments) {
    $args = implode(',',$arguments);
    $this-&gt;log('error', $name.'('.$args.') Not exists.', __METHOD__);
    return FALSE;
    }
    }