Как написать программу для определения серого адреса?
Вопрос в том, каким образом выявить признак "серости" адресаДа элементарно - если ваши сервисы доступны, значит белый, иначе серый.если такой адрес может начинаться с 77.ххх.ххх.ххх (так же, как и белый).Не может. Не конечно теоретически можно засунуть белый адрес за NAT, но никто в здравом уме так делать не будет.
Поэтому определяется элементарно.
Серые адреса начинаются на - 
10
100
127
169
172
192
Все остальные - белые.
Скорее всего вы не там смотрите адрес. 
Единственное место где можно смотреть адрес - интерфейс устройства которое получило адрес.
А то некоторые люди умудряются смотреть свой адрес на ресурсах вроде 2ip.ru... Не уподобляйтесь таким людям.
Адрес, начинающийся на 77 - белый. Список серых адресов фиксированный, официально задокументированный в RFC и вовсе не тайна. По ссылке смотрите адреса в таблице п.3 с пометкой "Private-Use Networks".
Увидеть реально выданный адрес вы можете только на роутере, т.к. если роутер получает серый адрес, значит для выхода в инет трафик должен проходить через NAT провайдера, где адрес подменяется и в инете вы уже с белым адресом в любом случае.
Обычно роутеры поддерживают не только веб управление, но и SSH и возможно telnet. Используя их вы можете скриптом получать адрес, проверять его и если он серый, то другим скриптом ребутить роутер (или даже не ребутить, а сбрасывать соединение и устанавливать снова). То же самое можно сделать и через веб интерфейс, но формировать свои HTTP запросы и парсить HTTP ответы роутера более утомительная задача, чем вариант с ssh/telnet.