I don't think this is possible with just nodes - there are no facilities to determine the depth below a surface. One solution is to use OSL to add a new node that can 'probe out' the surrounding geometry as in this answer as follows :
Enable Open Shader Language in the Render settings, open a Text Editor window, click New to create a new text block, set the name to something like 'mesh_proximity.osl' and paste the following code :
shader volume_meshproximity(
vector Point = P,
int Iterations = 1,
output float Min_Distance = 0.0,
output float Max_Distance = 0.0,
output float Avg_Distance = 0.0
) {
float x;
float y;
float z;
vector rand;
float scale = 5000.0;
float sum_dist = 0.0;
float max_dist = 0.0;
float min_dist = 0.0;
float Distance = 0.0;
for (int loop = 0; loop < Iterations; loop++)
{
rand = noise(Point*scale,loop*scale);
x = rand[0] - 0.5;
y = rand[1] - 0.5;
z = rand[2] - 0.5;
if(trace(Point,normalize(vector(x,y,z))))
{
getmessage("trace", "hitdist", Distance);
//getmessage("trace", "N", Normal);
//getmessage("trace", "hit", Hit);
}
if (loop == 0)
{
sum_dist = Distance;
max_dist = Distance;
min_dist = Distance;
}
else
{
sum_dist = sum_dist + Distance;
if (Distance > max_dist)
{
max_dist = Distance;
}
if (Distance < min_dist)
{
min_dist = Distance;
}
}
}
Max_Distance = max_dist;
Min_Distance = min_dist;
Avg_Distance = sum_dist / Iterations;
}
In the node editor add a Script node and set it to the text block you have just created. If all is well the OSL node will be compiled and you should have a new node that can be used in a Volume shader and provides Min, Max, and Average distance. This can be used as in the following material :
The new node projects rays from the sample point in the volume, determining how far they have travelled until they hit a surface. The number of rays is controlled by the Iterations - more rays results in less noise but takes longer to calculate. The Min_Distance returns the shortest distance for any of those rays, the Max_Distance the longest distance for any of those rays, and the Avg_Distance the average distance for all of those probe rays. Adjust the Divide node to scale the gradient and adjust the color ramp to adjust how the emission changes below the surface - similar can be done to control emission strength as well as color.
Here's my final render using the depth to control emission strength :
Blend file included
I have tried other solutions, without resorting to OSL (since OSL is not GPU compatible - you'll only be able to render on CPU) - such as using a smoke simulation to diffuse smoke out of the volume to achieve a gradient - but so far without success.
One promising alternative solution is to use a Point Density texture acting on a large number of particles distributed evenly over the surface using Grid distribution. However, you do need to increase the resolution quite high.
To achive this, add a Particle System to the mesh and set it to Emit From Faces with Grid enabled and Hexagonal Grid. Increase the particle grid Resolution until you have enough particles to give a dense enough covering (you might need to click in the field and type a values as the 'soft' limit is only 50. Then add the create the following nodes for the material :
Set the Object to your mesh and select the Particle System with Space set to 'World Space'. You can vary the Radius and Resolution to vary the effect. The Divide node can be used to vary the distance of the effect of the Color Ramp.