Monitor TCP/IP Port Consumption via PHP - php

So I'm running PHP on an Azure Web App. Recently, I ran into an issue with my server going into TCP/IP Port Exhaustion, because I was not using persistent connections to my Redis Cache. I don't believe the issue should come up again, but since I don't have any metrics available for this (and since I can't just remote into an Azure Web App), I was wondering if there's any functions in PHP that would allow me to see information about all the TCP ports currently in use by the server, so I can log that for diagnostics.
Does anyone have any ideas on how this can be accomplished? My initial thinking is that I would need to use shell_exec.

Unfortunately, I can't get this to work on Azure Web App, however I think this would work in other scenarios, where you are running your own server.
class netstat {
public $PortsInUse = 0;
public $AvailablePorts = 0;
public $TotalPorts = 0;
public $Ports = array();
public function __construct () {
$p = popen('netsh int ipv4 show dynamicport tcp', 'r');
$this->TotalPorts = rtrim(trim(explode("Number of Ports : ", stream_get_contents($p))[1]));
pclose($p);
$netstat = popen('netstat -no', 'r');
$log = stream_get_contents($netstat);
pclose($netstat);
$this->Ports = array_slice(explode("\n", $log), 4);
array_pop($this->Ports);
foreach($this->Ports as &$port) {
$port = explode(" ", $port);
foreach($port as $k => $p) {
if (empty($p))
unset($port[$k]);
}
$port = array_values($port);
$port = (object)array(
"LocalAddress" => $port[0],
"ForeignAddress" => $port[1],
"Status" => $port[2],
"ProcessId" => $port[3]
);
}
$this->PortsInUse = count($this->Ports);
$this->AvailablePorts = $this->TotalPorts - count($this->Ports);
}
}
The above object will be able to display the current number of TCP ports in use, and the total number of dynamic ports available for TCP on that machine. It also contains a "Ports" array, which contains information about each port in use, such as their local and foreign address, status and PID (process id).

Related

socket_sendto(): unable to write to socket [1]: Operation not permitted while using papertrail logging

I am trying to use papertrail as the logging channel in my laravel 8.X application. Whenever I use the following statement, it is throwing an exception
Log::channel('papertrail')->info('Something happened!');
socket_sendto(): unable to write to socket [1]: Operation not permitted
vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php:52
public function write($line, $header = "")
{
$this->send($this->assembleMessage($line, $header));
}
public function close(): void
{
if (is_resource($this->socket)) {
socket_close($this->socket);
$this->socket = null;
}
}
protected function send(string $chunk): void
{
if (!is_resource($this->socket)) {
throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore');
}
socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
}
protected function assembleMessage(string $line, string $header): string
{
$chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header);
return $header . Utils::substr($line, 0, $chunkSize);
}
}
Please advice.
You are getting this error because the log info you are sending is too big. (It probably works most of the time, but some larger errors are too big).
Laravel is using by default UDP to send the log to Papertrail.
The Papertrail accepts logs that UDP packets of up to 1024 bytes / TCP that are up to 100,000 bytes (~100 KB) long.
https://www.papertrail.com/help/troubleshooting-remote-syslog-reachability/#message-length
A solution is to use TCP. Since Laravel 9 there is an env variable to override this:
LOG_PAPERTRAIL_HANDLER = SocketHandler::class logging.php
For older versions of Laravel, you can override the config/logging.php to use the SocketHandler::class in stead of the SyslogUdpHandler::class.
Remark: not all shared hosting providers allow to make a TLS connection.

PHP KeepAlive program for Amazon

So im fairly new to PHP and i was assigned a small project by my manager, now my problem is that this is the first time doing anything like this so was wondering for some advice, guidance, help in any shape or form just as abit of a leg up,
So here's the description,
PROBLEM
Amazon EC2 can have multiple instances running behind a load balancer.
The load balancer will check at a URL i.e /_healthcheck to verify if the machine is functional.
The term functional can be defined as
Webserver can be accessed (implied by ability to connect to this check)
Webserver can connect to network resources CouchDB and Elastic Search
The node is not experiencing extremely high loads currenty(?)
Create a MVC for AWS EC2 to verify that the node is online
so far this is what code i've wrote, confused on how to satisfy time requirements for PHP (e.g check every 5 seconds etc)
class KeepaliveController extends AbstractActionController {
public function statusAction() {
$host = 'http://localhost:8089';
$port = 80;
$waitTime = 0;
$attempt = 1;
if($fp = fsockopen($host,$port,$errCode,$errStr,$waitTime)){
$response = $this->getResponse();
$response->setStatusCode(200);
} elseif ($waittime > 5){
echo "server busy retrying";
$response = $this->getResponse();
$response->setStatusCode(503);
elseif ($attempt > 5){
echo "Internal Error";
$response = $this ->getResponse();
$response->setStatusCode(500)
$attempt++
} else {
echo "server offline";
$reponse = $this->getResponse();
$reponse->setStatusCode(404);
}
}
as i said any help would be great.
Thank you

How to access FTP connection from different PHP file?

I am trying to create an FTP connection in PHP and trying to access it from other PHP files. Basically my goal is to create an FTP connection and make it available like a session when logging in and then access it from my other PHP files to do other tasks like file upload-download.
My connection class is as follows,
<?php
if($_GET['q'] == 'ftp_connect')
{
$connection = new connect_to_ftp;
echo $connection->ftp_connection();
}
elseif($_GET['q'] == 'get_connection_id')
{
$connection = new connect_to_ftp;
echo $connection->get_connection();
}
class connect_to_ftp
{
public $ftp_server = "";
public $username = "";
public $password = "";
public $connectionID, $login_result, $response;
public function ftp_connection()
{
$this->connectionID = ftp_connect($this->ftp_server);
if($this->connectionID==true)
{
$this->response = array("connection_error" => "Connected to ".$this->ftp_server);
$this->login_result = ftp_login($this->connectionID, $this->username, $this->password);
if($this->login_result==true)
{
$this->response = array("connection_error" => "Login successful to ".$this->ftp_server);
}else
{
$this->response = array("connection_error" => "Failed to login to ".$this->ftp_server." Check username and password");
}
}else
{
$this->response = array("connection_error" => "Could not connect to ".$this->ftp_server);
}
return json_encode($this->response);
}
public function get_connection()
{
return $this->connectionID;
}
}
?>
When I call ftp_connection() using ajax, it successfully connects to the ftp account but later on when I call get_connection() to return me the connection id, it returns me null instead.
Short answer: You can't
Longer answer: file handles, including sockets only exist within the process which opens them (this is not strictly true, it is possible to pass file handles between processes on Linux, but it is very contentious functionality and as with most esoteric things should not be used unless you fully understand the ramifications, and the functionality is not exposed in php).
The options are to either
1) create a connection, carry out the necessary operations then close it within the instance of a php script. Unfortunately FTP is even more badly thought than SMTP but nearly as deeply ingrained. So lots of people have invented built-in security "features" to try to address it's shortcomings. A common one is rate limiting of connections.
2) run an event based daemon to act as the FTP client and connect to that using php. However if you don't understand files and processes then you have a lot of learning to do before you can write such a programming.
Did I mention that FTP sucks? Learn how to use SFTP.

Is there a real proxy written in PHP or, what would I have to do to implement one?

I have been looking around on the web for a PHP proxy script and I can't find any. All I keep finding are scripts that download pages and edit src and href attributes in the HTML and, require me to browse to whatever website they're installed on. I don't need this, I need a real proxy listening on a port that I can set my browser to route all it's requests to.
What I'm looking to do is:
run a PHP script that will listen on some port of my own computer
configure my web browser to use localhost:port as a proxy
have the PHP script serve the page to my browser
All the so called proxy scripts written in PHP, that I have found, will fail miserably if the page requested uses XMLHttpRequest to fetch content because they won't see that request at all. No amount of link rewriting will solve the issue short of injecting some clever JavaScript that is unnecessary with a real proxy.
What I want in the end, is to have access to the requests and responses going back and forth between my browser and some remote server. I want to be able to use my browser's support for JavaScript, cookies, flash, etc. Basically, I want to have programmatic access to all the communication so I can analyze or manipulate it using PHP.
So, the questions are
Have I missed the real proxy implemented in PHP because of all the noise in my search results?
If there isn't a real proxy in PHP I would like to try making one. Are there resources online to help me learn what exactly I should do? (note, I RTM religiously: looking more for caveats and architecture of a basic proxy)
Links are appreciated. I know there are several MITM proxies out there but I want one in PHP.
I don't know if maybe I could do something with PHP's built-in webserver but I'll mess with that as well.
UPDATE
I've got a router script for the PHP built in webserver that is beginning to show promise. I can fire up the webserver and tell my web browser to use it as a proxy. The router script I've made differentiates between local and external resources and gives an easy way of handling either case. The only problem I have is with https. The server reports Invalid Request (Malformed HTTP Request). I think that means this server won't do https at all with just scripts and settings. I don't know. Maybe I'll be able to do it with Apache but transparently proxying https sounds hard, especially if I want to alter the data before it hits my browser.
AtropaToolbox/php_router/router.php
The router script my PHP built in webserver is pointed at, pulls in the actual classes from other files.
<?php
require_once('AtropaToolbox/php_proxy/proxy.php');
$proxy = new atropa_proxy();
if($proxy->process_request() === false) {
return false;
}
?>
AtropaToolbox/php_proxy/proxy.php
Extends atropa_mod_proxy to redefine the handlers.
<?php
require_once('AtropaToolbox/php_proxy/mod_proxy.php');
class atropa_proxy extends atropa_mod_proxy
{
protected function local_resource_handler() {
return false;
}
protected function external_resource_handler() {
$ext = $this->get_page();
//echo '<pre>' . print_r($ext, true) . '</pre>';
//$ext['page'] = preg_replace('/<a /', '<p ', $ext['page']);
$this->show_page($ext);
}
}
?>
AtropaToolbox/php_proxy/mod_proxy.php
The generic router script
<?php
/**
* Rev. 1 Atropa mod_proxy for php built in webserver
*/
class atropa_mod_proxy
{
protected function is_external_resource() {
$host = parse_url($_SERVER['REQUEST_URI'], PHP_URL_HOST);
if(isset($host) && $host !== $_SERVER['SERVER_NAME']) {
return true;
} else {
return false;
}
}
protected function local_resource_handler() {
return false;
}
protected function external_resource_handler() {
$ext = $this->get_page();
$this->show_page($ext);
}
public function process_request() {
if($this->is_external_resource()) {
return $this->external_resource_handler();
} else {
return $this->local_resource_handler();
}
}
public function get_request_headers() {
$arr = array();
foreach($_SERVER as $svar => $sval) {
if(substr($svar, 0, 4) === 'HTTP') {
$svar = substr($svar, 5);
$svar = preg_replace('/_/', ' ', $svar);
$svar = ucwords(strtolower($svar));
$svar = preg_replace('/ /', '-', $svar);
$arr[$svar] = $sval;
}
}
return $arr;
}
public function pack_request_headers($headers_array) {
$packed = '';
foreach($headers_array as $header_name => $header_value) {
$packed .= $header_name . ': ' . $header_value . "\r\n";
}
return $packed;
}
public function echo_response_headers($http_response_header_array) {
foreach($http_response_header_array as $val) {
if(strpos(strtolower($val), 'connection') !== 0) {
header($val);
}
}
}
protected function get_page() {
$request_headers = $this->get_request_headers();
$request_headers = $this->pack_request_headers($request_headers);
$method = $_SERVER["REQUEST_METHOD"];
$scheme = parse_url($_SERVER['REQUEST_URI'], PHP_URL_SCHEME);
$opts = array(
$scheme => array(
'method' => $method,
'header' => $request_headers
)
);
if(count($_POST) > 0) {
$content = http_build_query($_POST);
$opts[$scheme]['content'] = $content;
}
$context = stream_context_create($opts);
$ext = array();
$ext['page'] = file_get_contents($_SERVER['REQUEST_URI'], false, $context);
$ext['http_response_header'] = $http_response_header;
return $ext;
}
protected function show_page($ext) {
header_remove();
$this->echo_response_headers($ext['http_response_header']);
echo $ext['page'];
}
}
?>
Please read on Socket Programming with PHP and An Introduction to Sockets in PHP. You will be running a PHP Daemon to make PHP listen to a port and process all the requests.
In order to do this, you might want to look at http://sourceforge.net/projects/poxy/ so you can base your PHP Daemon there. You also have to learn how proxies communicate with clients. Poxy is a web-based application, you enter a URL and it loads it for you. It wouldn't allow you to listen to ports and it's not a php daemon so you will have to do a lot of coding for your PHP daemon proxy.

PHP Socket connection through proxy

I'm building a webmail-client-like application, and I'm having issues connecting to POP3 through our beloved corp proxy.
Due to client requirements, I'm obligated to use sockets to talk with their POP3 server (they actively specified this is mandatory and they also explained they have a proxy between the app server and the POP) so besides enabling me to work this is kind of the only option I have.
Does anyone know how to do this?
UPDATED TO ADD:
Here's my socket handler:
<?php
class Socket {
protected $handle = null;
protected static $status = null;
public function __construct($server, $port){
if(!$this->connect($server, $port)){
throw new UnexpectedValueException("Server $server in port $port unreachable.");
}
}
public static function getStatus(){
return self::$status;
}
public function write($string){
fputs($this->handle, $string);
return $this;
}
public function read($lines = 1){
$lines = abs((int)$lines);//people can be morons
for($i = 0; $i < $lines; $i++){
$response []= $this->getLine();
}
if($lines==1){
$response = $response[0];
}
return $response;
}
public function connect($server, $port){
$errNo = 0;
$handle = fsockopen($server, $port);
if(!$handle){
return false;
}
$this->handle = $handle;
return $this;
}
public function disconnect(){
if(gettype($this->handle)=='resource'){
fclose($this->handle);
}
}
public function __destruct(){
$this->disconnect();
}
protected function getLine(){
return fgets($this->handle);
}
}
I'm using it like so:
$plug = new Socket('mx.mailserver.com',110);
$plug->write("USER $username\n")->read();
$could = $plug->write("PASS $password\n")->read();
if(strpos($could,'+OK')!==false){
$mails = $plug->write("STAT\n");
}
And right now our proxy is not letting me out; situation I would like to know how to revert.
First, have you tested with telnet - i.e. if you are on the same server / workstation that the PHP script is running on, and you issue:
telnet mx.mailserver.com 110
Do you get the greeting? (you're also not reading that - so your read from the command where you send the username is going to get that as a response, so your code will work but largely by accident.
If you can't get it to work via telnet then stop and get that working first - no point proceeding otherwise.
You may need to send \r\n at the end of each command.
$plug->write("USER $username\r\n")->read();
So you need to do something like:
$plug = new Socket('mx.mailserver.com',110);
$greeting = $plug->read(); // check this said +OK
$plug->write("USER $username\r\n")->read(); // check this said +OK
$could = $plug->write("PASS $password\r\n")->read();
if(strpos($could,'+OK')!==false) {
$mails = $plug->write("STAT\r\n");
}
I'm not entirely sure about your strpos() line - but I can't test that right now.
As I say, before you do ANYTHING else verify that it all works ok on Telnet.
If it does, then monitor the server logs (if possible) and see whether you're getting in touch with the POP3 server and what it's getting.
Here's an example sequence:
telnet pop.blah.com 110
+OK Welcome to MailEnable POP3 Server
USER matthew
+OK
PASS mypassword
+OK
STAT
+OK 0 0
Hope this helps.
Use this for client
https://github.com/clue/php-socks
Use this for proxy server
https://github.com/clue/psocksd
If your server has more than one public IP and you need these IP act as proxy outgoing, use this for proxy server https://www.inet.no/dante/
Guide to configure proxy to have multi outgoing ip: http://www.inet.no/dante/doc/faq.html#multiple_external_ips
Example config to have multi outgoing ip: http://wiki.jokeru.ro/dante-socks-server
They all work for me

Categories