Can a node be accessible only by ajax? I'm using the ajax_links_api module to "ajaxify" a certain menu. When a menu button is clicked, the corresponding node loads into a specified div via ajax. This works well. 

The problem is that the nodes I want to load in this way should not be accessible as pages. I often create Drupal content that is only designed to appear in views, or as related content on other pages and is not supposed to be displayed by itself. My method is to use .htaccess to block these pages. But when I do that, the ajax can't access them either.

Is there a way to block access to pages in a browser but to allow requests coming from Drupal itself? Localhost access is not really an option since the site may well end up spread across different servers and virtual machines. 

If not, then can someone recommend an alternative to the ajax links module - perhaps I need to write some custom ajax that triggers Drupal to serve up a node "directly" rather than via a page - but I am confused about this and could use some pointers in the right direction. I must admit I find the "example" modules confusing!

EDIT: I've tried making a custom module as David Thomas suggests below and using hook_node_access. However this stops the ajax call from returning the content.
You can control access to nodes with

hook_node_access

For example, to restrict node viewing on node/[nid] pages:

/**
 * Implements hook_node_access
 */
function MYMODULE_node_access($node, $op, $account) {

  // If viewing node and URL path is node/[nid]
  // where [nid] is current $node-&gt;nid
  if($op == 'view' &amp;&amp; arg(0) == 'node' &amp;&amp; arg(1) == $node-&gt;nid){
    // Deny access to view current node page
    return NODE_ACCESS_DENY;
  }

}


You can add your own conditions to get more specific about access control there.

If you want to deny access to all node/%node/view pages, you can do it quite simply with:

hook_menu_alter

For example, set the access callback to FALSE

/**
 * Implements hook_menu_alter
 */
function MYMODULE_menu_alter(&amp;$items) {
  // Disable the node view page at node/%node
  $items['node/%node']['access callback'] = FALSE;
}